Return zero-copy views from large slice/substring/substr results#2506
Merged
Conversation
lahma
added a commit
to lahma/jint
that referenced
this pull request
Jun 7, 2026
Jint rows now reflect the empty-FDI, string-slice-view and global-binding-cache changes (PRs sebastienros#2502, sebastienros#2506, sebastienros#2507): object-string ~61 ms / 139 MB (was ~170 ms / 1.3 GB), stopwatch ~180 ms. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
String.prototype.slice/substring/substr now route through JsString.CreateSliced: whole-string results share the receiver/backing string outright, and large results covering at least half of the source (and >= 512 chars) become SlicedString - an immutable lazy view over the backing string (offset + length) that materializes only on ToString(). Small or low-coverage results keep copying so a short-lived view can never pin a much larger backing string. SlicedString never requires cloning (immutable), overrides indexer/Length/equality/hashing to operate span-based without materializing, and hashes identically to the equivalent flat string. TypeReference read JsString._value directly and now uses ToString(). MemoryProbe had attributed 89.9% + 9.2% of dromaeo-object-string''s 1.26 GB/op to slice/substring full copies. Gating (new StringSliceBenchmarks, same-window baselines): - SliceLargeDiscard 140.0ms -> 1.51ms (-98.9%), alloc 1.14GB -> 394KB - SubstringLargeDiscard 143.9ms -> 1.89ms (-98.7%), alloc 1.14GB -> 1.0MB - SliceThenRead 125.5ms -> 1.62ms (length/charCodeAt reads do not materialize) - SliceSmall guard unchanged (2.18 -> 2.19ms, alloc identical) - EngineComparison dromaeo-object-string wall-clock -53% (175.1 -> 81.8 ms/iter); per-op allocations 1,272MB -> 136MB (-89%); remaining substring copies are the intentional retention guard (12000-char result of a 131K source) - base64/regexp guards within driver noise - Jint.Tests 0 failures (net10.0 + net472), PublicInterface green, Test262 99208 passed / 0 failed Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
lahma
added a commit
to lahma/jint
that referenced
this pull request
Jun 8, 2026
Fresh full EngineComparison run on main with all five engine-comparison perf PRs merged (sebastienros#2502 empty-FDI, sebastienros#2503 eval cache, sebastienros#2504 prepared-script fix, sebastienros#2506 string slice views, sebastienros#2507 global-binding cache). Jint now: - dromaeo-object-string ~58-61 ms / 139 MB (rank 1, was ~170 ms / 1.3 GB and losing to NiL.JS) and the -modern variant likewise rank 1 - array-stress rank 1 (3,290 us, ParsedScript) - stopwatch 174-181 ms (was ~205 ms) - still the lowest allocations in nearly every workload Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
lahma
added a commit
that referenced
this pull request
Jun 8, 2026
…2505) * Refresh engine comparison results; add wall-clock profiling driver README.md: 2026-06-07 results on .NET 10.0.8 (Jurassic 3.2.9, NiL.JS 2.6.1722, YantraJS.Core 1.2.404 - all latest). Notes the severe YantraJS 1.2.404 regression on dromaeo-object-regexp (~35 s/op, ~32 GB allocated; 1.2.344 ran it at ~1 s/op). CpuProfileDriver adds a `--profile-cpu <script> <iters> <source|prepared>` mode mirroring EngineComparisonBenchmark per-op shape (fresh strict engine per iteration, dromaeo helper stubs) for quick wall-clock A/B comparisons, complementing the existing --profile-memory probe. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Add DateConstructionBenchmarks guard Records a falsified optimization hypothesis: skipping the redundant TimeClip + double round-trip in the `new Date()` now-path showed no measurable win (15.15ms +/- 0.38 -> 15.19ms +/- 0.21 per 100k constructions) because per-construction cost is dominated by dispatch, allocation and the UtcNow syscall. Kept as a guard for future Date work. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Update results table with run against fully-merged main Fresh full EngineComparison run on main with all five engine-comparison perf PRs merged (#2502 empty-FDI, #2503 eval cache, #2504 prepared-script fix, #2506 string slice views, #2507 global-binding cache). Jint now: - dromaeo-object-string ~58-61 ms / 139 MB (rank 1, was ~170 ms / 1.3 GB and losing to NiL.JS) and the -modern variant likewise rank 1 - array-stress rank 1 (3,290 us, ParsedScript) - stopwatch 174-181 ms (was ~205 ms) - still the lowest allocations in nearly every workload Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 15, 2026
This was referenced Jun 24, 2026
This was referenced Jul 6, 2026
This was referenced Jul 13, 2026
This was referenced Jul 20, 2026
This was referenced Jul 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
String.prototype.slice/substring/substrallocated a fullstring.Substringcopy for every result. MemoryProbe attributed 89.9% + 9.2% of dromaeo-object-string''s 1.26 GB/op to exactly this.What
The three methods now route through
JsString.CreateSliced:slice(0)on aJsStringreceiver);SlicedString— an immutable lazy view (offset + length) over the backing string, nested besideConcatenatedString. It materializes only onToString()(cached), overrides indexer/Length/equality span-based (no materialization forlength/charCodeAt/comparisons), hashes identically to the equivalent flat string, and — being immutable — never requires cloning, so it can be stored into bindings/properties without flattening;TypeReferencereadJsString._valuedirectly (the only such site outside JsString.cs) and now usesToString().Measurements (new
StringSliceBenchmarks, same-window baselines, 128K char source)EngineComparison
dromaeo-object-string: wall-clock −53% (175.1 → 81.8 ms/iter), per-op allocations 1,272 → 136 MB (−89%) — the remaining MBs are the intentional retention-guard copies. base64/regexp guards unchanged.Verification
Jint.Tests0 failures (net10.0 + net472), PublicInterface green🤖 Generated with Claude Code