6 ms·
There are some tricks to make interpreters very fast.
by ant6n 2y ago
There are some tricks to make interpreters very fast.
- deaddodo 2y agoThose tricks are called compilation (whether that be AOT, JIT, or a mix of the two).
- ant6n 2y agoNo, then it’s not an interpreter anymore.
- deaddodo 2y agoYes, that was the point. The tricks to make interpreters fast are to make them not interpreters. This one is already using just about all the tricks in the book to make a "fast" interpreter and it's performance is a drip compared to a JIT version.
- ant6n 2y agoQEMU interpreter uses all the tricks? Very much doubt that. QEMU is a JIT first, built around maximum flexibility, not performance. A dedicated, optimized x86 on ARM interpreter could probably get 20% off the performance of QEMU Jit, if not more.
- kragen 2y agoi wouldn't describe sacrificing 80% of the machine's native performance as 'very fast'. a moped goes 40 km/hour; a ferrari goes 200 km/hour. you're paying for a ferrari but getting a moped
- ant6n 2y agoAn interpreter that runs at 20% native speed would be considered a very fast interpreter. That would be an order of magnitude faster than a „trickle“.
- kragen 2y agowhat i'm saying is that, because an interpreter that runs at 20% native speed would be considered a very fast interpreter, which is still very slow, there are in most cases no tricks for making interpreters very fast
- deaddodo 2y agoDo you actually have any experience with systems emulation, JIT/AOT compilation, Apple's x86->ARM hardware assistance that it's JIT interfaces offer, etc? Or are you just speaking off the cuff in a very general manner? Because it very much sounds like the latter. I have, quite extensively. I can assure you, that the source set they are using most definitely does use all the "tricks" (the chief two being threaded code [no, not that threading] and preoptimized jump tables). I can also assure you that losing the hardware acceleration offered by Apple's extensions and the general performance boost JIT/AOT offer is much more than 80%. But, sure. For argument's sake, let's accept your (incorrect) premise. Taking a 1ghz potential emulated target processor down to 200mhz is a fairly drastic drop. Disallowing a whole slew of modern code/target OSes and verging the usability on nil.
- kragen 2y agothe best i've been able to do with things like numpy, threaded interpretive forth, and ocamlc is about 15–20% of native performance. is that what you mean by 'very fast'? i wouldn't call that 'very fast' but it is an order of magnitude faster than cpython i guess for example, this ocaml program runs 6× slower when compiled with ocamlc (which uses an excellent bytecode interpreter) than with ocamlopt let rec fib n = if n <= 2 then 1 else fib (n-1) + fib (n-2) and n = 40 in Printf.printf "fib(%d) = %d\n" n (fib n) ;; the ocamlopt-compiled version is about 5% slower than a handwritten assembly version (and orders of magnitudes slower than a version compiled with gcc, which is why i wrote the assembly version)
- ant6n 2y agoWell, we’re talking about emulation here, not a bytecode interpreter for a high level dynamically typed language. CPython is fairly slow, it’s written in C in a fairly understandable way, effectively using a large switch statement. There’s like three jumps or so per executed bytecode, it probably uses some jump table. „All the tricks“ for an interpreter would mean 1 jump per interpreted instruction, or perhaps 0.5 for some of them. It would probably mean no explicit jump tables. It would probably mean the interpreter is set up pipelined like a real cpu - loading instructions on parallel with executing previous instructions. You can get perhaps 5-15% of native speed using for an interpreter all the tricks. QEMU can maybe get 20-50% (not sure these days actually, I haven’t followed improvements for a while). Rosetta can get close to 100%, using a JIT but also hardware that is specifically designed to aid emulation (memory accesses like on x86). Given nowadays CPUs execute like 3-5 instructions per cycle, getting 5-15% performance for an interpreter would be very fast and very difficult to achieve, but possible - if designed from the ground up for performance.
- kragen 2y agoi think it's unusual to hit 3-5 ipc sustained in normal code, but it seems like we're in broad agreement about quantitatively what kind of performance an interpreter can achieve. i mentioned three interpretive systems that do reach about 15% of native single-threaded performance with very different approaches: the ocaml bytecode interpreter, threaded interpretive code like gforth, and numpy it's just that i call 15% of native performance 'very slow' and you call it 'very fast', because you're comparing the moped to the walker you're used to, and i'm comparing it to a sports car because that's what you're paying for instruction set jitting getting a speedup instead of a slowdown goes back to last millennium with hp's dynamo https://dl.acm.org/doi/pdf/10.1145/349299.349303 https://dl.acm.org/doi/pdf/10.1145/349299.349303 and was central to transmeta's business plan. qemu's jit is sort of simpleminded to make it easier to maintain