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)„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.
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 and was central to transmeta's business plan. qemu's jit is sort of simpleminded to make it easier to maintain
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.
A dedicated, optimized x86 on ARM interpreter could probably get 20% off the performance of QEMU Jit, if not more.
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.