Repository navigation
perf(runtime): marshal C string arguments with a single allocation - #525
Open
edusperoni wants to merge 1 commit into
Open
edusperoni wants to merge 1 commit into
edusperoni wants to merge 1 commit into
Conversation
Each string passed to a char* parameter went through String::Utf8Value (one allocation), strdup (a second allocation and copy) and a separately allocated OneByteStringResource. The resource now owns its bytes inline: NewUtf8Copy sizes one block for the resource plus the UTF-8 copy and has V8 write straight into it, with the same flags Utf8Value uses, and Dispose() frees the block. The external string that ties the copy's lifetime to the GC is unchanged, so a pointer into the argument stays valid exactly as long as before.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This branch has not been deployed
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.
Stacked on #524 (base
fix/cstring-arg-lifetime); review that first.Motivation
Every JS string passed to a
char*parameter took three allocations and two copies before the call:String::Utf8Value:Utf8LengthV2, allocation,WriteUtf8V2strdupof that buffer: second allocation and copy, then the first is freednewedOneByteStringResourceChanges
OneByteStringResource::NewUtf8Copysizes onemallocblock for the resource plus the UTF-8 bytes and has V8 write straight into it, with the same flagsUtf8Valueuses (kNullTerminate | kReplaceInvalidUtf8, so lone surrogates still become U+FFFD).Dispose()destroys the resource and frees the block. The destructor is private, so the resource can only be released throughDispose().The external string that ties the copy's lifetime to the GC is unchanged, so a pointer into the argument is valid exactly as long as before. Returned aliases (
strchr,strstr),strtol'sendptrandstrtok's saved state behave the same.Benchmarks
Release build, iPhone 16 Pro simulator, median of 5 alternating launches, each the best of 7 timed trials (ns per call).
strlenkeeps the native side negligible, so the deltas are marshalling cost.labs(-1)(no string, baseline)strlen("")strlen(8 ASCII)strlen(64 ASCII)strlen(64 non-ASCII)strlen(4 KB ASCII)* Not part of this PR: this PR with the GC-tie external string removed (the copy leaks), built only to measure what that string still costs. About 15–25 ns per call, or 8–10% of a short-string call. That's the most a call-owned copy (freed when the call returns) could still save, and it would shorten pointer lifetimes, which can't be done compatibly. Not pursued.
Benchmark spec
Run with the Release A/B harness (
run_bench.sh build/run/compare_bench.py); the spec only needsstrlenandlabsfrom the SDK metadata.Tests
No new specs: the output is byte-for-byte the same, so the existing C-string specs (including #524's
""and external Latin-1 cases) cover it.-a): 1837 tests, 0 failures, no ASan reports.