From 1e3c27b7aa0b3727c4f637ed9bcad0521f878c47 Mon Sep 17 00:00:00 2001 From: Eli White Date: Sun, 19 Apr 2026 23:31:20 -0700 Subject: [PATCH] perf: swap writer's spread-with-deltaTime for Object.assign MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tsup transpiles `{...ev, deltaTime: 0}` to __spreadProps(__spreadValues(...)) which iterates property descriptors — ~7% of total writer profile time was spent inside __spreadProps. Object.assign({}, ev, { deltaTime: 0 }) is a native builtin on V8 and 2-3× faster for small objects. Applied at the three writer sites that clone-with-delta-reset a source event: buildUnrecognizedTrack (top-level unrecognized MIDI tracks) and the per-track unrecognizedMidiEvents passes in buildDrumTrack and buildFretTrack. Measured on writer autoresearch bench (2000 charts, 8 workers): previous: 5.710 ms mean, 4.883 ms p50, 15.040 ms p95, 5.132s wall now: 4.566 ms mean, 4.129 ms p50, 10.424 ms p95, 4.926s wall delta: -20.0% mean, -30.7% p95 Second run (variance check): 4.609 ms mean — stable. 0 hash mismatches, 442/442 tests still green. Cumulative: baseline 92 ms -> 4.57 ms, 20× faster. --- src/chart/midi-writer.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/chart/midi-writer.ts b/src/chart/midi-writer.ts index 96b214a..e51be26 100644 --- a/src/chart/midi-writer.ts +++ b/src/chart/midi-writer.ts @@ -257,7 +257,10 @@ function buildUnrecognizedTrack(events: MidiEvent[]): MidiEvent[] { const out: MidiEvent[] = [] for (const e of events) { const absTick = e.deltaTime - out.push({ ...e, deltaTime: absTick - prevTick }) + // Object.assign is noticeably faster than {...e, …} spread on V8 — tsup + // transpiles the spread to __spreadProps(__spreadValues(...)) which + // iterates property descriptors. + out.push(Object.assign({}, e, { deltaTime: absTick - prevTick }) as MidiEvent) prevTick = absTick } return out @@ -539,7 +542,7 @@ function buildDrumTrack( events.push({ tick: ev.deltaTime, seq: unrecSeqBase + unrecSeq++, - event: { ...ev, deltaTime: 0 } as MidiEvent, + event: Object.assign({}, ev, { deltaTime: 0 }) as MidiEvent, }) } } @@ -1002,7 +1005,7 @@ function buildFretTrack( events.push({ tick: ev.deltaTime, seq: unrecSeqBase + unrecSeq++, - event: { ...ev, deltaTime: 0 } as MidiEvent, + event: Object.assign({}, ev, { deltaTime: 0 }) as MidiEvent, }) } }