From e7ea8c76bd649aa84fdeb084fec02529743ee6eb Mon Sep 17 00:00:00 2001 From: Uri Shaked Date: Sat, 12 Dec 2020 15:01:17 +0200 Subject: perf(cpu): speed up event system ditch `array.sort()` and instead manually keep the array sorted when we insert a new item. --- src/cpu/cpu.ts | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) (limited to 'src/cpu/cpu.ts') diff --git a/src/cpu/cpu.ts b/src/cpu/cpu.ts index e7a2544..a609222 100644 --- a/src/cpu/cpu.ts +++ b/src/cpu/cpu.ts @@ -173,23 +173,29 @@ export class CPU implements ICPU { } } - private updateClockEvents() { - this.clockEvents.sort((a, b) => a.cycles - b.cycles); - this.nextClockEvent = this.clockEvents[0]?.cycles ?? 0; - } - addClockEvent(callback: AVRClockEventCallback, cycles: number) { const entry = { cycles: this.cycles + Math.max(1, cycles), callback }; - this.clockEvents.push(entry); - this.updateClockEvents(); + // Add the new entry while keeping the array sorted + const { clockEvents } = this; + if (!clockEvents.length || clockEvents[clockEvents.length - 1].cycles <= entry.cycles) { + clockEvents.push(entry); + } else if (clockEvents[0].cycles >= entry.cycles) { + clockEvents.unshift(entry); + } else { + for (let i = 1; i < clockEvents.length; i++) { + if (clockEvents[i].cycles >= entry.cycles) { + clockEvents.splice(i, 0, entry); + break; + } + } + } + this.nextClockEvent = this.clockEvents[0].cycles; return callback; } updateClockEvent(callback: AVRClockEventCallback, cycles: number) { - const entry = this.clockEvents.find((item) => item.callback === callback); - if (entry) { - entry.cycles = this.cycles + Math.max(1, cycles); - this.updateClockEvents(); + if (this.clearClockEvent(callback)) { + this.addClockEvent(callback, cycles); return true; } return false; @@ -199,18 +205,22 @@ export class CPU implements ICPU { const index = this.clockEvents.findIndex((item) => item.callback === callback); if (index >= 0) { this.clockEvents.splice(index, 1); - this.updateClockEvents(); + this.nextClockEvent = this.clockEvents[0]?.cycles ?? 0; + return true; } + return false; } tick() { - if (this.nextClockEvent && this.nextClockEvent <= this.cycles) { - const clockEvent = this.clockEvents.shift(); - clockEvent?.callback(); - this.nextClockEvent = this.clockEvents[0]?.cycles ?? 0; + const { nextClockEvent, clockEvents } = this; + if (nextClockEvent && nextClockEvent <= this.cycles) { + clockEvents.shift()?.callback(); + this.nextClockEvent = clockEvents[0]?.cycles ?? 0; } - if (this.interruptsEnabled && this.nextInterrupt >= 0) { - const interrupt = this.pendingInterrupts[this.nextInterrupt]; + + const { nextInterrupt } = this; + if (this.interruptsEnabled && nextInterrupt >= 0) { + const interrupt = this.pendingInterrupts[nextInterrupt]; avrInterrupt(this, interrupt.address); if (!interrupt.constant) { this.clearInterrupt(interrupt); -- cgit v1.2.3