-
-
Notifications
You must be signed in to change notification settings - Fork 161
perf(runtime): streamline DataView numeric setters #10134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
proggeramlug
wants to merge
3
commits into
PerryTS:main
from
proggeramlug:codex/issue-10089-dataview-setter
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| # DataView numeric setter fast path (#10089) | ||
|
|
||
| `binary-dataview-set.ts` and `binary-dataview-get.ts` are the unchanged, | ||
| standalone reproducers embedded in issue #10089. Their seeded setup, minimum | ||
| 200 ms/five-run warmup, seven samples of at least 20 ms, median calculation, | ||
| fresh-input policy, and per-invocation checksum checks are preserved. | ||
|
|
||
| Measured on 2026-09-12 on Linux x86_64 with an AMD Ryzen 7 7700X (16 logical | ||
| CPUs), Node 26.5.1, LLVM 22.1.8, and the pinned nightly-2026-08-20 Rust | ||
| toolchain. Before is current main `50e08e91dd6a54d9d9210c43a5d36c86d880d144` | ||
| (Perry 0.5.1539); after is this change on the same commit. Both builds used | ||
| `--release --locked`, `CARGO_PROFILE_RELEASE_CODEGEN_UNITS=16`, the same package | ||
| set, and matching compiler/runtime/stdlib archives. Compilation used | ||
| `--no-auto-optimize` with `PERRY_RUNTIME_DIR` pointing at those archives. Runs | ||
| were serialized. Source and executable hashes are in `artifacts.json`. | ||
|
|
||
| ## Current-main comparison | ||
|
|
||
| Times are median milliseconds per workload invocation. The setter workload | ||
| writes and immediately reads every value; the getter control only reads. Every | ||
| Perry checksum matched Node at every size. | ||
|
|
||
| | n | Before Perry setter | After Perry setter | After Node setter | Before ratio | After ratio | After getter ratio | | ||
| |---:|---:|---:|---:|---:|---:|---:| | ||
| | 100 | 0.006030 | 0.005387 | 0.000269 | 22.50x | 20.03x | 11.52x | | ||
| | 1,000 | 0.058436 | 0.052222 | 0.002510 | 23.36x | 20.80x | 12.46x | | ||
| | 10,000 | 0.581095 | 0.518971 | 0.024820 | 23.51x | 20.91x | 12.35x | | ||
| | 100,000 | 5.730139 | 5.192406 | 0.247603 | 23.26x | 20.97x | 12.33x | | ||
| | 1,000,000 | 58.591890 | 51.767301 | 2.471560 | 23.70x | 20.95x | 12.31x | | ||
|
|
||
| The Perry setter workload improves by 9.4–11.6% and is 1.72–1.76 times the | ||
| getter control, rather than the issue's original 6.68 times at 1M. The | ||
| remaining difference includes a second accessor per iteration and numeric | ||
| wrapping/storage; the getter baseline itself remains out of scope. Raw results | ||
| are `before.json` and `after.json`. | ||
|
|
||
| Least-squares log(time)/log(n) slopes remain linear: before setter Perry 0.997, | ||
| Node 0.992; after setter Perry 0.996, Node 0.992. After getter slopes are Perry | ||
| 0.999 and Node 0.994. | ||
|
|
||
| ## Pre-change attribution | ||
|
|
||
| The two original costs were measured independently on the issue's pinned | ||
| revision `9495bfc95e2afcfb5a7cb535e440e61ec0722cb1`, before changing behavior. | ||
| The no-handle-scope patch is a timing diagnostic only. The no-propagation patch | ||
| redirects the write to the canonical shared backing before removing the old | ||
| reverse-table propagation, preserving checksums and modeling the storage design | ||
| that subsequently landed in #10071. | ||
|
|
||
| | n | Historical baseline | No handle scope | Direct backing/no propagation | Getter control | | ||
| |---:|---:|---:|---:|---:| | ||
| | 100 | 0.006275 | 0.006034 (-3.8%) | 0.005392 (-14.1%) | 0.002951 | | ||
| | 1,000 | 0.062615 | 0.059653 (-4.7%) | 0.053234 (-15.0%) | 0.029187 | | ||
| | 10,000 | 0.618650 | 0.592610 (-4.2%) | 0.529090 (-14.5%) | 0.290650 | | ||
| | 100,000 | 6.176727 | 5.909852 (-4.3%) | 5.307551 (-14.1%) | 2.906022 | | ||
| | 1,000,000 | 51.473179 | 48.430062 (-5.9%) | 51.179968 (-0.6%) | 29.168526 | | ||
|
|
||
| Across the stable 100–100k range, propagation/view-table work was consistently | ||
| the dominant extra setter cost, 3.2–3.6 times the handle-scope cost. The 1M | ||
| propagation row reproduces the threshold anomaly already called out in the | ||
| issue and is not used to reverse the four-size attribution. Getter controls at | ||
| 100k were 2.9060, 2.8957, and 2.9139 ms across the three builds. | ||
|
|
||
| #10071 landed at `1ae0f84497` between the pinned and current-main measurements. | ||
| It made views share canonical backing storage and deleted the reverse-table | ||
| propagation call. This change removes the remaining setter-only work: DataView | ||
| construction caches the stable backing byte pointer, and calls whose offset and | ||
| value are already Numbers neither probe `VIEW_REGISTRY` nor publish a transient | ||
| GC handle. Coercing and BigInt calls retain the handle and reload the receiver | ||
| after user code. | ||
|
|
||
| Raw attribution data and the exact diagnostic patches are committed alongside | ||
| the current-main comparison. | ||
|
|
||
| ## Reproduce | ||
|
|
||
| From the checkout being measured: | ||
|
|
||
| ```sh | ||
| export CARGO_PROFILE_RELEASE_CODEGEN_UNITS=16 | ||
| cargo build --release --locked \ | ||
| -p perry -p perry-runtime-static -p perry-stdlib-static | ||
| export PERRY_RUNTIME_DIR="$PWD/target/release" | ||
| target/release/perry compile \ | ||
| benchmarks/issue-10089/binary-dataview-set.ts \ | ||
| --no-auto-optimize -o /tmp/binary-dataview-set | ||
| target/release/perry compile \ | ||
| benchmarks/issue-10089/binary-dataview-get.ts \ | ||
| --no-auto-optimize -o /tmp/binary-dataview-get | ||
| python3 benchmarks/issue-10089/measure.py \ | ||
| --set-app /tmp/binary-dataview-set \ | ||
| --get-app /tmp/binary-dataview-get \ | ||
| --node node \ | ||
| --output /tmp/results.json | ||
| ``` | ||
|
|
||
| Do not run timed processes or builds concurrently. Rebuild all three packages | ||
| when changing checkouts. | ||
|
|
||
| ## Semantic and GC validation | ||
|
|
||
| `test_gap_10089_dataview_setter_fast_path.ts` covers both byte orders and all | ||
| numeric kinds, byte-level endianness, out-of-range and negative offsets, | ||
| ToNumber strings/objects/abrupt completion, BigInt/Number type errors, | ||
| ToBigInt-before-bounds ordering, detach during coercion, BigInt round trips, and | ||
| DataView/Uint8Array writes in both directions. Its coercion callback allocates, | ||
| calls `gc()`, and runs under forced evacuation, from-space protection, and | ||
| evacuation verification. Its output matches Node 26.5.1 byte-for-byte. | ||
|
|
||
| The focused runtime test also checks that a windowed DataView stores the exact | ||
| backing pointer in its private payload and writes through it. |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,202 @@ | ||
| [ | ||
| { | ||
| "workload": "binary-dataview-set", | ||
| "engine": "node", | ||
| "name": "binary-dataview-set", | ||
| "category": "binary-node", | ||
| "n": 100, | ||
| "ms_per_run": 0.00026892069596076023, | ||
| "runs": 519811, | ||
| "checksum": 53205556 | ||
| }, | ||
| { | ||
| "workload": "binary-dataview-set", | ||
| "engine": "perry", | ||
| "name": "binary-dataview-set", | ||
| "category": "binary-node", | ||
| "n": 100, | ||
| "ms_per_run": 0.0053867756531115986, | ||
| "runs": 25268, | ||
| "checksum": 53205556 | ||
| }, | ||
| { | ||
| "workload": "binary-dataview-set", | ||
| "engine": "node", | ||
| "name": "binary-dataview-set", | ||
| "category": "binary-node", | ||
| "n": 1000, | ||
| "ms_per_run": 0.0025101219879519144, | ||
| "runs": 55706, | ||
| "checksum": 509007827 | ||
| }, | ||
| { | ||
| "workload": "binary-dataview-set", | ||
| "engine": "perry", | ||
| "name": "binary-dataview-set", | ||
| "category": "binary-node", | ||
| "n": 1000, | ||
| "ms_per_run": 0.05222245691905451, | ||
| "runs": 2663, | ||
| "checksum": 509007827 | ||
| }, | ||
| { | ||
| "workload": "binary-dataview-set", | ||
| "engine": "node", | ||
| "name": "binary-dataview-set", | ||
| "category": "binary-node", | ||
| "n": 10000, | ||
| "ms_per_run": 0.02482009553349933, | ||
| "runs": 5643, | ||
| "checksum": 6182819 | ||
| }, | ||
| { | ||
| "workload": "binary-dataview-set", | ||
| "engine": "perry", | ||
| "name": "binary-dataview-set", | ||
| "category": "binary-node", | ||
| "n": 10000, | ||
| "ms_per_run": 0.5189708461538495, | ||
| "runs": 273, | ||
| "checksum": 6182819 | ||
| }, | ||
| { | ||
| "workload": "binary-dataview-set", | ||
| "engine": "node", | ||
| "name": "binary-dataview-set", | ||
| "category": "binary-node", | ||
| "n": 100000, | ||
| "ms_per_run": 0.24760332098765048, | ||
| "runs": 567, | ||
| "checksum": 64481668 | ||
| }, | ||
| { | ||
| "workload": "binary-dataview-set", | ||
| "engine": "perry", | ||
| "name": "binary-dataview-set", | ||
| "category": "binary-node", | ||
| "n": 100000, | ||
| "ms_per_run": 5.192406250000033, | ||
| "runs": 28, | ||
| "checksum": 64481668 | ||
| }, | ||
| { | ||
| "workload": "binary-dataview-set", | ||
| "engine": "node", | ||
| "name": "binary-dataview-set", | ||
| "category": "binary-node", | ||
| "n": 1000000, | ||
| "ms_per_run": 2.4715601111110774, | ||
| "runs": 62, | ||
| "checksum": 455838306 | ||
| }, | ||
| { | ||
| "workload": "binary-dataview-set", | ||
| "engine": "perry", | ||
| "name": "binary-dataview-set", | ||
| "category": "binary-node", | ||
| "n": 1000000, | ||
| "ms_per_run": 51.76730099999986, | ||
| "runs": 7, | ||
| "checksum": 455838306 | ||
| }, | ||
| { | ||
| "workload": "binary-dataview-get", | ||
| "engine": "node", | ||
| "name": "binary-dataview-get", | ||
| "category": "binary-node", | ||
| "n": 100, | ||
| "ms_per_run": 0.000265062859490542, | ||
| "runs": 510455, | ||
| "checksum": 53205456 | ||
| }, | ||
| { | ||
| "workload": "binary-dataview-get", | ||
| "engine": "perry", | ||
| "name": "binary-dataview-get", | ||
| "category": "binary-node", | ||
| "n": 100, | ||
| "ms_per_run": 0.0030535497709917123, | ||
| "runs": 45860, | ||
| "checksum": 53205456 | ||
| }, | ||
| { | ||
| "workload": "binary-dataview-get", | ||
| "engine": "node", | ||
| "name": "binary-dataview-get", | ||
| "category": "binary-node", | ||
| "n": 1000, | ||
| "ms_per_run": 0.0024278540907988313, | ||
| "runs": 52452, | ||
| "checksum": 509006827 | ||
| }, | ||
| { | ||
| "workload": "binary-dataview-get", | ||
| "engine": "perry", | ||
| "name": "binary-dataview-get", | ||
| "category": "binary-node", | ||
| "n": 1000, | ||
| "ms_per_run": 0.03023969788519657, | ||
| "runs": 4632, | ||
| "checksum": 509006827 | ||
| }, | ||
| { | ||
| "workload": "binary-dataview-get", | ||
| "engine": "node", | ||
| "name": "binary-dataview-get", | ||
| "category": "binary-node", | ||
| "n": 10000, | ||
| "ms_per_run": 0.024489498164015678, | ||
| "runs": 5264, | ||
| "checksum": 6172819 | ||
| }, | ||
| { | ||
| "workload": "binary-dataview-get", | ||
| "engine": "perry", | ||
| "name": "binary-dataview-get", | ||
| "category": "binary-node", | ||
| "n": 10000, | ||
| "ms_per_run": 0.30233589552238305, | ||
| "runs": 467, | ||
| "checksum": 6172819 | ||
| }, | ||
| { | ||
| "workload": "binary-dataview-get", | ||
| "engine": "node", | ||
| "name": "binary-dataview-get", | ||
| "category": "binary-node", | ||
| "n": 100000, | ||
| "ms_per_run": 0.24528795121951136, | ||
| "runs": 573, | ||
| "checksum": 64381668 | ||
| }, | ||
| { | ||
| "workload": "binary-dataview-get", | ||
| "engine": "perry", | ||
| "name": "binary-dataview-get", | ||
| "category": "binary-node", | ||
| "n": 100000, | ||
| "ms_per_run": 3.0253681428571246, | ||
| "runs": 49, | ||
| "checksum": 64381668 | ||
| }, | ||
| { | ||
| "workload": "binary-dataview-get", | ||
| "engine": "node", | ||
| "name": "binary-dataview-get", | ||
| "category": "binary-node", | ||
| "n": 1000000, | ||
| "ms_per_run": 2.4499883333333323, | ||
| "runs": 61, | ||
| "checksum": 454838306 | ||
| }, | ||
| { | ||
| "workload": "binary-dataview-get", | ||
| "engine": "perry", | ||
| "name": "binary-dataview-get", | ||
| "category": "binary-node", | ||
| "n": 1000000, | ||
| "ms_per_run": 30.166053000000034, | ||
| "runs": 7, | ||
| "checksum": 454838306 | ||
| } | ||
| ] |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| { | ||
| "date": "2026-09-12", | ||
| "host": { | ||
| "os": "Linux 6.17.0-23-generic x86_64", | ||
| "cpu": "AMD Ryzen 7 7700X 8-Core Processor", | ||
| "logical_cpus": 16 | ||
| }, | ||
| "toolchain": { | ||
| "node": "v26.5.1", | ||
| "node_sha256": "fb48e77df2f8e92fedfec39afa60a5f41563441f6b61316ada5fb295a431c2c6", | ||
| "rustc": "1.100.0-nightly (f7d782a3b 2026-08-19)", | ||
| "cargo": "1.100.0-nightly (514c56dd7 2026-08-19)", | ||
| "llvm": "22.1.8" | ||
| }, | ||
| "build": { | ||
| "profile": "release", | ||
| "locked": true, | ||
| "codegen_units": 16, | ||
| "auto_optimize": false, | ||
| "packages": [ | ||
| "perry", | ||
| "perry-runtime-static", | ||
| "perry-stdlib-static" | ||
| ] | ||
| }, | ||
| "sources": { | ||
| "binary-dataview-set.ts": "c01d0c04e4e99fcc6725ee83d1a70cee6647217110c95a850d93ad98128375d3", | ||
| "binary-dataview-get.ts": "9693aea9afe91fb2ce471aee496fe3e883482a61e304400a1436d7cb411d32e8" | ||
| }, | ||
| "builds": { | ||
| "attribution_baseline": { | ||
| "commit": "9495bfc95e2afcfb5a7cb535e440e61ec0722cb1", | ||
| "set_executable_sha256": "90f9ab906bb0df83f34fcb72f51efe06aec72c78474371ac3f003ada3826e5c4", | ||
| "get_executable_sha256": "9323e511ab8bb320c50895b97af9f15468792b446c0f81adbcded234c8ecbd91" | ||
| }, | ||
| "attribution_no_handle_scope": { | ||
| "commit": "9495bfc95e2afcfb5a7cb535e440e61ec0722cb1", | ||
| "patch": "diagnostic-no-handle-scope.patch", | ||
| "set_executable_sha256": "d7cd59357fc0792d53a9ff2bb69b74a741fd264123fe5bbf608b95b738e3abb7", | ||
| "get_executable_sha256": "54584620ec9285184ab06a69eeee4665c72f5d3c1abdb840feebde03bb7c7ce5" | ||
| }, | ||
| "attribution_no_view_propagation": { | ||
| "commit": "9495bfc95e2afcfb5a7cb535e440e61ec0722cb1", | ||
| "patch": "diagnostic-no-view-propagation.patch", | ||
| "set_executable_sha256": "2011401cade07d244a6ce6d92af4dd866376c157c5ade98920e6cbb102598df0", | ||
| "get_executable_sha256": "3ff30ca899c87c73643f304d5a879d53fd00b4b984bd0e5c49ef9e28faee07c9" | ||
| }, | ||
| "before": { | ||
| "commit": "50e08e91dd6a54d9d9210c43a5d36c86d880d144", | ||
| "set_executable_sha256": "aec304da5fa6683767c99ab62477d5a4b381ff0e85d5112a00da4e7c703d16da", | ||
| "get_executable_sha256": "ffd6bc041b0c615d3c332ebc0b602361bbd573b6bd1f73ae0748baba1207743d" | ||
| }, | ||
| "after": { | ||
| "commit": "50e08e91dd6a54d9d9210c43a5d36c86d880d144 plus working-tree change", | ||
| "set_executable_sha256": "29b33320719fff409c63eb2fee2b7aa229dfe4f3f72cc9f6ed6aaafed0fe7bc2", | ||
| "get_executable_sha256": "6dfe429b8c7234237a423179c16a961cb92ee0a6502a3a2cc3df05273cb61491", | ||
| "gap_executable_sha256": "a6538dd5cdb69f268d28e26c7d8c19a0c979a3ee5774d4da7ac4fca16e507bb5", | ||
| "perry_sha256": "1895d1da6a43549f66f569b633eb8efbdd7001fdd1bf87a0d216f2be7ff4ed4d", | ||
| "runtime_archive_sha256": "f2d99f5266c20d3ac1bd91cae23834bac877b9855f770de6fe04c6545b193f6d", | ||
| "stdlib_archive_sha256": "265917df8c9e3d28a5f1b1c210db114fea7fb89ec9d253f533a42a291acc21e6" | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Record a reproducible revision for the after build.
Line 54 does not identify the source used for the measured after executable.
plus working-tree changecannot be checked out or reproduced. The benchmark source hashes do not identify the runtime changes.Record the PR-head commit, or commit and retain the exact dirty patch with its digest. This lets reviewers rebuild and validate the reported performance result.
🤖 Prompt for AI Agents