5 ms·
Thanks for writing this. I am curious if you benchmarked the giant switch implementation? While the current VM has some benefits (no bytecode, easy to pass argu
by celeritascelery 2y ago
Thanks for writing this. I am curious if you benchmarked the giant switch implementation? While the current VM has some benefits (no bytecode, easy to pass argument's, cleaner compiler, etc ) it also has some performance overhead. Some that I am thinking of:
1. Every instruction results in functional call overhead, which is something that tail calls (with protect_none) avoid.
2. Because you are using closures the next instruction has to be heap allocated. I don’t know what closures look like in Go, but there will involve some indirection.
3. Every iteration of the loop requires a bounds check on ip.
Now, none of these may matter for SQL because as the blog post said, the instructions are quite large. And it already shows huge improvements over the AST interpreter. I am just curious how the switch would benchmark.
On an unrelated note. Using closures to write an interpreter brought to mind this talk
https://m.youtube.com/watch?v=V8dnIw3amLA&list=PLFTr8ChfQg9t9quFJNSoRwVHQhLFfTYnV https://m.youtube.com/watch?v=V8dnIw3amLA&list=PLFTr8ChfQg9t...
- ncruces 2y agoNot the author. Each instruction is an heap allocated closure, but it's allocated at “compile” time (when you generate the instruction from the AST), not at runtime (every time you run the instruction): by then they're (preallocated) free standing functions that receive the VM. Every iteration of the loop in a big switch bytecode interpreter also requires a bounds checks.