Skip to content

perf: simplify _validateMapping — hot path first, drop redundant 'in' checks#66

Merged
7rulnik merged 1 commit into
mainfrom
perf/validate-mapping-cleanup
May 10, 2026
Merged

perf: simplify _validateMapping — hot path first, drop redundant 'in' checks#66
7rulnik merged 1 commit into
mainfrom
perf/validate-mapping-cleanup

Conversation

@7rulnik
Copy link
Copy Markdown
Owner

@7rulnik 7rulnik commented May 10, 2026

Summary

_validateMapping runs once per addMapping call (when skipValidation is false, the default). Two cleanups, both behavior-preserving:

  1. Drop redundant 'X' in Y membership tests. The previous form had:

    aGenerated && 'line' in aGenerated && 'column' in aGenerated
      && aGenerated.line > 0 && aGenerated.column >= 0

    The numeric > 0 / >= 0 checks already subsume the 'in' tests — undefined > 0 and 'abc' > 0 are both false, so missing or non-numeric coords still fall to the error branches. The in operator walks the prototype chain on every check; the four redundant ones cost real time per addMapping.

  2. Reorder: hot path first. Case 2/3 (full mapping with original + source) is what every bundler emit hits. Check it first and return. The friendly-error branch (original.line/column not numbers) and the generic invalid-mapping branch stay reachable for the cold cases — error messages and codepaths are unchanged.

Bench

SOLO=1 PHASES=adding scripts/bench-diff.sh main generate (two-process, ops/sec via benchmark.js):

fixture cand ops/sec base ops/sec Δ
amp.js.map 482 ±0.34% 449 ±0.28% +7.3%
babel.min.js.map 71.87 ±0.48% 69.19 ±0.55% +3.9%
issue-41.js.map 92.38 ±0.80% 87.79 ±0.89% +5.2%
preact.js.map 12,125 ±0.24% 10,969 ±0.12% +10.5%
react.js.map 4,513 ±0.26% 4,094 ±0.18% +10.2%
vscode.map 8.43 ±2.44% 7.92 ±3.44% +6.4%

Mean ~+7.3%. babel.min sees +3.9% here vs +0.2% on #65 — the prototype-walk savings hit every mapping unconditionally, so the two PRs stack rather than overlap.

Test plan

  • All 205 tests pass — error-message contracts preserved (/Invalid mapping/, /original\.line and original\.column are not numbers/)
  • Coverage: 98.35 / 97.21 / 96.75 — source-map-generator.js stays 100/100/100

… checks

The previous form had:
  aGenerated && 'line' in aGenerated && 'column' in aGenerated
    && aGenerated.line > 0 && aGenerated.column >= 0

The numeric `> 0` / `>= 0` checks already subsume the `'line' in X`
membership tests — `undefined > 0` and `'abc' > 0` are both false, so
missing or non-numeric coords still fall to the error branches.
The `in` operator does a prototype-chain walk per check; dropping the
four redundant ones removes a measurable per-addMapping cost.

Also reordered: case 2/3 (full mapping) is the hot path on every
bundler emit; check it first and return. The friendly-error path
(original.line/column not numbers) and the generic invalid-mapping
path stay reachable for the cold cases.

Bench (SOLO=1 PHASES=adding generate vs main, two-process):
  preact +10.5%, react +10.2%, amp +7.3%, vscode +6.4%,
  issue-41 +5.2%, babel.min +3.9% — mean ~+7.3%
@7rulnik 7rulnik merged commit 97bfb50 into main May 10, 2026
3 checks passed
@7rulnik 7rulnik deleted the perf/validate-mapping-cleanup branch May 10, 2026 21:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant