perf: track sorted state incrementally in ReplaceSource#241
Conversation
Instead of unconditionally setting _isSorted = false on every replace()/insert() call, compare the new element against the last one. When replacements are added in source order (the common case in webpack, since AST traversal is position-ordered), the array stays marked as sorted and _sortReplacements() becomes a no-op flag check. Benchmark results (ops/s, higher is better): getReplacements(): 7,637 → 13,643 (+78.7%) source() (1 replacement): 101,919 → 107,040 (+5.0%) source() (1000 small): 6,135 → 6,609 (+7.7%) replace() x1000: 244,693 → 218,742 (-10.6%, per-call check) insert() x1000: 244,665 → 216,147 (-11.7%, per-call check) The replace/insert per-call overhead (~11ns) is a deliberate trade-off: downstream consumers (source, map, streamChunks) skip an entire O(n log n) sort when data is already ordered. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: bf5f0f3 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #241 +/- ##
==========================================
- Coverage 97.58% 97.54% -0.04%
==========================================
Files 25 25
Lines 2069 2078 +9
Branches 668 672 +4
==========================================
+ Hits 2019 2027 +8
- Misses 47 48 +1
Partials 3 3
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Merging this PR will improve performance by ×2.3
|
|
Closing this PR after further analysis — the optimization is not net-positive in realistic scenarios. Why:
The |
Summary
_isSorted = falseon everyreplace()/insert()call, compare the new element against the last one_sortReplacements()becomes a no-op flag checkfalseand the normalArray.prototype.sort()runsBenchmark results (ops/s, higher is better)
The
replace()/insert()per-call overhead (~11ns) is a deliberate trade-off: downstream consumers (source(),map(),streamChunks()) skip an entire O(n log n) sort when data is already ordered.All 89,869 tests pass.
Test plan
yarn lintpassesnpx jest --no-coverage— 89,869 tests passnpm run benchmark🤖 Generated with Claude Code