Synthetic IR Studio · development benchmark note · 2026

Browser Render-Time Comparison

A small practical comparison of the same Fat Plate synthesis workload across Apple hardware and desktop/mobile browsers. No Windows/PC results are included because no PC was available for testing.

What was measured

The benchmark uses Synthetic IR Studio's built-in Render Time readout, measuring wall-clock time from pressing Generate until the Web Worker returns the completed impulse response. Each reported condition uses three runs of the same Fat Plate preset. The purpose is not to benchmark the machines generally; it is to document how this particular browser-based numerical DSP workload behaves in the tested environments.

Important: these figures describe this renderer, preset and test setup only. They should not be read as general claims that one browser, JavaScript engine or device is universally faster than another.

Results

HardwareBrowserRuns (s)MeanRangeσ
M4 MaxFirefox3.94, 4.02, 4.074.01 s0.13 s0.05
M4 MaxChrome5.14, 5.18, 5.195.17 s0.05 s0.02
M4 MaxSafari5.86, 5.93, 6.025.94 s0.16 s0.07
M2 UltraFirefox6.17, 6.13, 6.146.15 s0.04 s0.02
iPhone 15 ProFirefox8.32, 7.50, 7.487.77 s0.84 s0.39
iPhone 15 ProSafari8.61, 7.55, 8.588.25 s1.06 s0.49
M2 UltraSafari12.11, 12.31, 12.1812.20 s0.20 s0.08
Fastest observed4.01 sM4 Max · Firefox
M4 browser spread1.48×Safari time relative to Firefox
M2 browser spread1.98×Safari time relative to Firefox
Phone browser difference5.8%Firefox lower mean time than Safari

Three useful comparisons

1. Browser choice on identical M4 Max hardware. Firefox averaged 4.01 s, Chrome 5.17 s, and Safari 5.94 s. Relative to Firefox, Chrome required about 29% more wall time and Safari about 48% more. Because the hardware and synthesis workload were unchanged, this isolates a substantial browser/runtime contribution.

2. The M2 Ultra Safari result is the major outlier. On the same M2 Ultra, Firefox averaged 6.15 s while Safari averaged 12.20 s: Safari took approximately 1.98× as long. The three Firefox runs were especially tight, spanning only 0.04 s, so the difference is much larger than the observed run-to-run variation.

3. Mobile performance is genuinely practical. The iPhone 15 Pro averaged 8.25 s in Safari and 7.77 s in Firefox. Unlike the desktop tests, both iOS browsers use Apple's required WebKit browser engine, so the close results are unsurprising and should not be interpreted as an independent SpiderMonkey-versus-JavaScriptCore comparison. Even so, an approximately eight-second Fat Plate render demonstrates that the full browser implementation is usable on current phone hardware.

Interpretation

Synthetic IR Studio's generation path is dominated by numerical JavaScript running in a Web Worker rather than by DOM rendering or GPU work. The Fat Plate workload contains long-running DSP loops, typed-array processing, modal and stochastic synthesis, filtering, stereo transformations and selective high-rate processing. Browser JavaScript engines can optimise such workloads differently through JIT compilation, loop optimisation, typed-array handling, bounds-check elimination, inlining, allocation behaviour and worker scheduling.

The present measurements therefore suggest that browser/runtime behaviour is a significant part of render performance. On the tested Macs, Firefox produced the lowest render times. Hardware generation also remains important: Firefox improved from 6.15 s on the M2 Ultra to 4.01 s on the M4 Max, a reduction of about 35%.

The measurements do not identify which internal engine optimisation is responsible. Establishing that would require stage-level profiling of the renderer—for example separately timing Plate construction, modal/statistical generation, high-rate DSP, filtering, stereo processing and decimation.

Current takeaway

The useful finding is simple: the same Synthetic IR Studio design can vary markedly in render time according to browser as well as hardware. In this small test, M4 Max + Firefox was the fastest combination at approximately 4.01 seconds, while the same M4 Max required about 5.17 seconds in Chrome and 5.94 seconds in Safari. The iPhone 15 Pro completed the same workload in roughly eight seconds, confirming that the renderer remains practical on mobile hardware despite the complexity of the synthesis path.

Diagnostic Investigation · Stages 1–9

Scope. The original browser comparison established a large render-time spread for one fixed Synthetic IR Studio workload. The following staged investigation localised that spread without changing the production DSP. Unless stated otherwise, the diagnostic workload was Plate · Fat / Long Bloom 001, seed 847291, 48 kHz, 7 s stereo, 336,000 samples, selective HQ_OS 8, cold Plate cache and cold Worker. Timings below are diagnostic measurements, not general browser benchmarks.

Interpretive rule. Ablation timings are not assumed to be additive. Changing a hot JavaScript path can change generated code and JIT behaviour. The investigation therefore uses controls and independent reconstructions to localise effects, while avoiding claims about unobserved compiler internals.

Stage 1 · Worker-level localisation

The first instrumented build separated Worker execution from UI/message overhead and coarse DSP stages. On the M2 Ultra, non-Worker overhead was negligible (approximately 12–13 ms). The dominant difference was inside the broad modal/diffuse/event field: JavaScriptCore (JSC) required 11.194 s versus 5.388 s for SpiderMonkey (SM), while the selective HQ 8× chain showed the opposite ordering (JSC 0.805 s versus SM 1.198 s). This ruled out a general “one browser is faster” explanation and pointed to an engine × code-structure interaction.

Stage 2 · Late-field localisation

HardwareEngineLate fieldHQ chainWhole Worker
M4 MaxSpiderMonkey3.261 s0.665 s4.019 s
M4 MaxV84.194 s0.866 s5.157 s
M4 MaxJavaScriptCore5.449 s0.439 s6.019 s
M2 UltraSpiderMonkey5.361 s1.187 s6.674 s
M2 UltraV86.147 s1.278 s7.557 s
M2 UltraJavaScriptCore11.114 s0.803 s12.085 s

Plate setup, modal construction and modal population were approximately 0–1 ms and therefore not responsible. The desktop late-field ordering was consistently SM → V8 → JSC, whereas the HQ chain favoured JSC. On iPhone 15 Pro, Safari/WebKit late field was 6.609 s and Firefox iOS/WebKit 6.909 s; because both iOS browsers use WebKit, the desktop-style SpiderMonkey advantage did not appear. This provided a useful negative control.

Stage 3 · Workload isolation inside the late field

Late-field workloadSpiderMonkeyV8JavaScriptCore
Full control5.361 s6.147 s11.114 s
Modal only5.332 s6.072 s11.095 s
Diffuse only0.111 s0.110 s0.148 s
Events only0.097 s0.096 s0.141 s

Modal-only execution reproduced virtually the entire late-field cost and the complete cross-engine ordering. Diffuse and event workloads were small and V8/SM were effectively tied. The dominant divergence was therefore localised specifically to the modal computation.

Stage 4 · Modal-loop ablations

Modal workloadSpiderMonkeyV8JavaScriptCore
Control5.292 s6.381 s11.204 s
Remove Math.exp4.608 s3.029 s4.173 s
Remove Math.sin1.890 s4.381 s7.637 s
Remove exp + sin0.840 s0.587 s1.196 s
State/property baseline0.712 s0.528 s1.039 s

At this stage the JSC-specific slowdown followed the path containing exponential decay: removing Math.exp reduced JSC by 62.8%, whereas removing sine reduced it by 31.8%. However, these were ablations rather than isolated function benchmarks, so the result implicated the decay path but did not establish that raw exponential evaluation was the cause. One anomalous Firefox state run (346 ms late field accompanied by 879 ms Architecture and 114 ms Ambience) was rejected; the clean repeat was 712 ms.

Stage 5 · Decay-expression isolation

ConditionSpiderMonkeyV8JavaScriptCore
A · State/property0.730 s0.513 s0.882 s
B · Arithmetic, no exp0.802 s0.555 s1.046 s
C · Simple changing Math.exp1.613 s1.293 s1.398 s
D · Actual decay Math.exp1.660 s1.406 s1.539 s
E · Precomputed inverse tau1.592 s1.324 s1.553 s
F · Recursive decay0.917 s0.717 s1.249 s

This overturned the simple “JSC has slow Math.exp” interpretation. In the isolated simple-exp test JSC was faster than SM, and in the isolated actual decay expression all three engines clustered between 1.406 and 1.660 s. Precomputing the inverse decay constant produced only small changes. The large Stage-4 penalty therefore required interaction between the decay path and its surrounding modal-loop context. Recursive decay was faster in this diagnostic, particularly in V8 and SM, but was retained only as a possible later optimisation and was not introduced into production.

Stage 6 · Controlled reconstruction

Starting from the isolated actual decay expression, the Stage-4 no-sine arithmetic was rebuilt cumulatively under JSC: actual exp + sink 1.596 s; real L/R accumulation 1.590 s; + modal amplitude 1.657 s; + left pickup 1.739 s; + both pickups 1.860 s. The progression was smooth and never reproduced the 7.637 s Stage-4 no-sine result. Restoring the numerical workload was therefore insufficient: surrounding code structure still mattered.

Stage 7 · Diagnostic predicate placement

A Stage-4 no-sine path was rebuilt with invariant diagnostic predicates hoisted outside the hot sample loop. JSC late-field time was 7.667 s versus the Stage-4 reference of 7.637 s (+0.4%). Predicate placement was therefore rejected as the explanation.

Stage 8 · Invariant RT60/tau hoisting

A mechanical comparison exposed a remaining structural difference. The slow path recomputed the mode-invariant expression Math.max(.15, +p.rt60/1000) inside the sample × mode loop; the fast reconstruction had already evaluated that term once outside the loop. Stage 8 changed only this placement.

EngineRepeated invariant expressionHoisted tauReduction
SpiderMonkey1.890 s1.834 s3.0%
V84.381 s1.524 s65.2%
JavaScriptCore7.667 s1.873 s75.6%

This was the principal localisation result. After hoisting, the large engine disparity largely disappeared: V8 became fastest, while SM and JSC differed by only 39 ms. The result does not establish that Math.max or property access is generally slow in either engine; it demonstrates a strong engine-sensitive optimisation effect for this invariant expression in this particular deeply nested numerical DSP path.

Stage 9 · Invariant-expression decomposition

Safari / JSC conditionLate field
A · Full repeated Math.max(.15,+p.rt60/1000)8.712 s
B · Repeated property/coercion only7.254 s
C · Repeated property/coercion + division6.918 s
D · Repeated Math.max on hoisted scalar2.260 s
E · Fully hoisted tau2.718 s

Stage 9 was designed for localisation rather than absolute ranking and introduced a multi-way diagnostic branch, so the individual timings should not be treated as additive operation costs. Nevertheless, the regime split was clear: conditions retaining repeated +p.rt60 property access/coercion remained slow (6.918–8.712 s), whereas conditions with the property value hoisted were much faster (2.260–2.718 s). Repeated division was not required, and repeated Math.max on an already-hoisted scalar did not reproduce the slow regime.

Production Validation · Invariant Hoist

After Stages 1–9 were complete, the Stage-8 finding was applied to a copy of the complete production renderer. The DSP algorithm was not changed: the invariant expression Math.max(.15,+p.rt60/1000) was evaluated once outside the hot sample × mode loop and the resulting scalar was used by the existing modal-decay Math.exp calculation. No recursive decay approximation, mode reduction, quality reduction, RNG change, or other DSP modification was introduced.

Browser / enginePre-fix referenceOptimised productionChange
Safari / JavaScriptCore12.20 s5.72 s−53.1%
Chrome / V87.557 s*5.26 s−30.4%
Firefox / SpiderMonkey6.674 s*6.61 s−1.0%

*Chrome and Firefox pre-fix references are the M2 Ultra Stage-2 complete-Worker measurements; Safari's 12.20 s value is the original three-run production mean. The optimised values are complete production-render readouts from the invariant-hoist build under the fixed Plate · Fat / Long Bloom 001 / seed 847291 / 48 kHz / 7 s / stereo workload.

The production result reproduced the diagnostic engine sensitivity: JavaScriptCore gained dramatically, V8 gained substantially, and SpiderMonkey was essentially unchanged. The post-fix complete-render ordering was Chrome 5.26 s, Safari 5.72 s, Firefox 6.61 s, with only 1.35 s between fastest and slowest.

Output equivalence. The untouched and invariant-hoisted production builds were rendered with identical deterministic settings and their exported pristine WAV files were compared directly. Both contained 336,000 stereo frames (672,000 samples) at 48 kHz / 24-bit. There were zero differing samples; maximum absolute sample difference was 0, RMS difference was 0, and the complete WAV files had the identical SHA-256 digest 3333eb794bead308b59bbec8f401f418bd38037db6fd0642f68e0311bb9097cb. The optimisation therefore produced a byte-for-byte identical deterministic output for the validation render.

Conclusion

The original desktop result — Firefox/SpiderMonkey substantially faster than Safari/JavaScriptCore for this Plate render — was not a general browser-speed effect. The investigation localised the difference from the whole render to the Worker, then to the late field, then to the modal loop, then to the decay-containing path. Isolated exponential evaluation behaved normally across engines. The decisive intervention was to hoist an invariant RT60-derived tau from the deeply nested sample × mode loop. In the clean Stage-8 comparison this reduced the no-sine modal workload by 75.6% in JSC and 65.2% in V8, but only 3.0% in SM.

Stage 9 further associated the JSC slow regime with repeated access/coercion of the invariant object property p.rt60 inside that hot decay path. However, this should not be interpreted as a demonstrated failure of loop-invariant code motion or as evidence that ordinary property access is intrinsically expensive in JavaScriptCore. A series of subsequent standalone tests progressively reconstructed the relevant workload: first the invariant expression in a nested numerical loop, then per-mode object access, then mutable modal phase and drift state with stereo oscillators, and finally a substantially reconstructed Plate late-field context including block processing, diffuse state, modal mutation, plate noise-bed calculations, and output accumulation. None reproduced the production slowdown; in the closest extracted benchmark the repeated and hoisted forms were effectively identical at 1567 ms and 1570 ms respectively.

The production effect is therefore best described as a context-dependent engine/JIT optimisation interaction in the complete renderer. Its precise internal cause may depend on wider code structure, execution order, object and mutation history, optimisation state, or other interactions not preserved by the reduced benchmarks. Determining the exact browser-engine mechanism would require progressively reducing the known-positive full renderer, potentially with engine-specific JIT instrumentation. That investigation would have little practical benefit to Synthetic IR Studio: the performance problem has been isolated sufficiently to remove it without changing the DSP, and further reduction would primarily amount to browser-engine archaeology rather than application optimisation.

Production status. The invariant hoist has now passed full-production validation. Under the fixed benchmark it reduced Safari render time from the original 12.20 s mean to 5.72 s, reduced Chrome to 5.26 s, left Firefox effectively unchanged at 6.61 s, and produced a byte-for-byte identical deterministic WAV. This mathematically equivalent invariant hoist is therefore retained as the optimised production implementation.