4 ms·
Squeezing a Little More Performance Out of Bytecode Interpreters
- astrobe_ 3y ago> Our results suggest that it can give large improvements when training for a specific benchmark. > improved the execution speed of the program for which the order was optimized between 0.8% and 23.0% with 7.7% on average. Single-digit speedup is not worth it IMO, and the wide range (<1% - 23%) probably means that you specialize for some tasks at the expense of other types of tasks, which is not for everyone's interpreter. One use I can see for it is to compile multiple inner loops and have the interpreter switch between them (probably manually), if that can get us the yummy 20% speedup. Core primitives and dispatchers are usually not the biggest part of interpreters, after all. Maybe in this scenario the core primitives could also benefit from small semantic changes, like no bounds checking for instance.
- eldenring 3y agoIt would be cool to see this compared with a more simple bin packing technique, or even just stuffing the most commonly used instructions at the top and those ordered by size.
- dvh 3y agothe eJSVM link is broken: http://spa.info.kochi-tech.ac.jp/~ugawa/ejs-comlan-preprint.pdf http://spa.info.kochi-tech.ac.jp/~ugawa/ejs-comlan-preprint....
- dazzawazza 3y agowayback machine has a single cache for the curious: https://web.archive.org/web/20221030174643/http://spa.info.kochi-tech.ac.jp/~ugawa/ejs-comlan-preprint.pdf https://web.archive.org/web/20221030174643/http://spa.info.k... interesting read.
- smarr 3y agoYeah, the serve seems to be temporarily down. The paper can also be found here: https://tugawa.github.io/ejs-comlan-preprint.pdf https://tugawa.github.io/ejs-comlan-preprint.pdf
- runehol 3y agoThe key problems with this approach is not mentioned in the blog post, but is shown in figures 6 and 7 of the paper - https://stefan-marr.de/downloads/acmsac23-huang-et-al-optimizing-the-order-of-bytecode-handlers-in-interpreters-using-a-genetic-algorithm.pdf https://stefan-marr.de/downloads/acmsac23-huang-et-al-optimi... Basically, the code handler ordering does not generalise well across benchmark nor processor, so to get the speedup they see, you'd need a specialised interpreter for your specific benchmark and processor. That puts this into the "interesting, but not very practical" category.
- CmdDot 3y agoFrom the post: «In the context of resource-constraint embedded devices, it may make sense to tailor an interpreter to a specific applications to gain best performance.» The «key problems» are also discussed in the introduction of the paper at the top of page 2 - including why it’s practical in their context. Also in the paper, they say speedups based on optimizing a subset of benchmarks generalize to other benchmarks as well, but not across environments. Last I checked, starting with an «optimizing your environment» task, is far from being considered «not very practical»
- _a_a_a_ 3y agoCome on man, they literally say that, and acknowledge hardware may differ in behaviour, that difference too to be subsumed by the training/optimising.
- jonstewart 3y agoI wish there was a bit more analysis of the properties/qualities of reorderings that improved performance. Also, how do the improvements intersect with profiler-guided optimization?
- _a_a_a_ 3y agoThis is my area of interest and I know a little about interpretation/compiling. I'm a little dubious about this (which I shouldn't be because the benchmarks speak for themselves). But a couple of doubts. 1. "it avoids an extra jump to the top of the loop at the end of each bytecode" – but the top of the loop is a known, hardcoded value, so the prefetcher should be able to take the unconditional jump at little or no cost. 2. "we have multiple dispatch points instead of a single one" which is supposed to assist branch prediction - I made a big "oooh!" at that, but thinking it over, the target of the GOTO is computed each time eg. push_local: void* target = targets[index]; index += /* ... */ goto *target; So I don't see how the branch predictor has that much to work on. I suppose it cuts down on the possible number of targets so it's more likely to predict correctly, and reading again, that's exactly what they say "we may only see a subset of bytecodes, which increases the chance that the processor can predict the jump correctly". Hmm, I'm a bit surprised that makes that much of a difference but a quick look at the benchmarks suggest they are really pretty small. I'd expect the technique to lose its speedup as the amount of code grows. Perhaps if you wanted speed then picking out common bits of code and inlining it would cut down on the branches and possibly make the code more compact, for better cache use. (that's a bit petty though, it's clearly not the target of their research). I suppose if you had some spare byte codes left over and you have a commonly used instruction, perhaps 'add', you might have a few different versions of add (add1, add2, add3) which behaved identically but were scattered through the 'source' code, to help the branch predictor even more.
- deleted 3y ago[deleted]
- superdimwit 3y agoOn 1: this small amount of overhead matters because the amount of work you do on each opcode can be tiny. The extra jump could be 20% of your runtime! On 2: yes, this helps the indirect branch target predictor. In a real program you’ll often get repeated sequences of opcodes (increment, then compare) that can be predicted. These branch predictors can be pattern based.
- kaba0 3y agoSo you are questioning the effect of direct threading code? Because I assure you, that has a significant impact compared to the naive switch-eval loop, on the order of 2-4x from my experience. (Source: have written a JVM interpreter with the naive approach that is approximately that much slower than the OpenJDK with disabled JIT compiler. It was later also confirmed by people working on the actual JVM that that’s roughly the order of difference between the two approaches. Unfortunately I can’t find a great article on the topic right now (google is beyond useless recently)). The article is about a further small improvement over this much larger and commonly implemented one.
- dddnzzz334 3y agoDidn't know goto labels can be treated as values. TIL: https://stackoverflow.com/q/1777990 https://stackoverflow.com/q/1777990
- superdimwit 3y agohttps://eli.thegreenplace.net/2012/07/12/computed-goto-for-efficient-dispatch-tables https://eli.thegreenplace.net/2012/07/12/computed-goto-for-e... is a good summary