Use idempotent loads of the bytecode. - #24
Merged
Conversation
I've done this fairly differently from the previous approach, which (in the terminology of this PR) only exposed `load_ip_uint8_`. This commit tries to reduce the number of calls by using `load_ip_uint32`: that allows common cases (e.g. small integers of 8 bytes) to be done without further idempotent calls. The hope -- and benchmarking vs. the previous approach seems to confirm this -- is that it reduces the overhead when we're interpreting. I experimented with several designs: loading 64 bits and decoding integers that way but some mp instructions can be >8 bytes, and it seems that the sweet spot is either "is 2 or 3 bytes" or "is 9 or 10 bytes". So that was slower than the 32 bit approach (and, really, we could get away with 24 bits in this commit, as we never use more than 3 bytes). There are a couple of gotchas with this commit: it bakes in a little endian assumption; it requires architectures that allow unaligned 32-bit reads; and we have to allow at least 3 bytes padding after the last instruction. In terms of performance, this hugely speeds up some benchmarks, but it does slow some down. Despite the latter, this commit (relative to the preceeding commit) seems to clearly be heading in the right direction: ``` BigLoop/ykmp/1000000000 2759692 ± 146 227746 ± 976 0.08 91.75% faster Sieve/ykmp/3000 178133 ± 228 19497 ± 59 0.11 89.05% faster Mandelbrot/ykmp/500 128149 ± 843 44276 ± 1156 0.35 65.45% faster List/ykmp/1500 134336 ± 149 62093 ± 626 0.46 53.78% faster NBody/ykmp/250000 191769 ± 5127 112451 ± 92 0.59 41.36% faster Queens/ykmp/1000 84899 ± 598 70252 ± 557 0.83 17.25% faster CD/ykmp/250 186601 ± 627 209803 ± 1146 1.12 12.43% slower Permute/ykmp/1000 115033 ± 710 133177 ± 171 1.16 15.77% slower Richards/ykmp/100 305566 ± 1433 355874 ± 361 1.16 16.46% slower Bounce/ykmp/1500 89773 ± 264 122221 ± 811 1.36 36.14% slower Towers/ykmp/600 103125 ± 555 153793 ± 312 1.49 49.13% slower Storage/ykmp/1000 90828 ± 318 112431 ±31069 1.24 indistinguishable ```
Pavel-Durov
approved these changes
Jul 28, 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.
I've done this fairly differently from the previous approach, which (in the terminology of this PR) only exposed
load_ip_uint8_. This commit tries to reduce the number of calls by usingload_ip_uint32: that allows common cases (e.g. small integers of 8 bytes) to be done without further idempotent calls. The hope -- and benchmarking vs. the previous approach seems to confirm this -- is that it reduces the overhead when we're interpreting.I experimented with several designs: loading 64 bits and decoding integers that way but some mp instructions can be >8 bytes, and it seems that the sweet spot is either "is 2 or 3 bytes" or "is 9 or 10 bytes". So that was slower than the 32 bit approach (and, really, we could get away with 24 bits in this commit, as we never use more than 3 bytes).
There are a couple of gotchas with this commit: it bakes in a little endian assumption; it requires architectures that allow unaligned 32-bit reads; and we have to allow at least 3 bytes padding after the last instruction.
In terms of performance, this hugely speeds up some benchmarks, but it does slow some down. Despite the latter, this commit (relative to the preceeding commit) seems to clearly be heading in the right direction: