3 ms·
The fact that the performance of an implementation varies significantly depending on the actual CPU could already be deduced from some of the Ertl papers. More
by astrobe_ 11y ago
The fact that the performance of an implementation varies significantly depending on the actual CPU could already be deduced from some of the Ertl papers.
Moreover, given that one uses specifically a bytecode interpreter and not a JIT is generally the sign that the interpreter is to be used on multiple platforms. "Optimizing" in this context simply means (almost) nothing.
The obvious conclusion is to not care too much about raw performance and focus instead on ease of interfacing with libraries, and to make it easy to add primitives/instructions to your VM. With the idea that if your interpreter is too slow, you just rewrite the critical parts in native code.
- mafribe 11y agogiven that one uses specifically a bytecode interpreter and not a JIT is generally the sign that the interpreter is to be used on multiple platforms. Well, you could JIT the bytecode. Or you could use a meta-tracer (see e.g. [1]). Both (kind-of / sort-of) circumvent the platform dependency problem. [1] http://tratt.net/laurie/research/pubs/html/bolz_tratt__the_impact_of_metatracing_on_vm_design_and_implementation/ http://tratt.net/laurie/research/pubs/html/bolz_tratt__the_i...
- vardump 11y ago> you just rewrite the critical parts in native code. Rewrite critical parts of interpreter in native code? My point was there's no optimal native code anymore. Pure interpreters are falling out of fashion anyways. For JITted systems, there's a significant cost for calling native code. At least until JITs actually inline natively called code, possibly even through dynamic library (.so, .dylib, .dll, etc.) call. We need a lightweight, thin profile guided JIT/AOT engine. No standard library, memory management agnostic. Something that can target different architectures, memory & cache configurations and instruction set extensions that may have been unknown at design phase. A compilation target for some C/C++/Rust/etc. and a runtime that takes care of the architecture details.
- astrobe_ 11y ago> Rewrite critical parts of interpreter in native code? My point was there's no optimal native code anymore. No, I mean rewrite the critical parts of the "interpreted" program as interpreter primitives/instructions: the best way to eliminate interpreter overhead is to merge N primitives into one. But I realise we have a different perspective. You seem to consider interpreter VMs as off the shelf components, when I consider VMs as custom components because I'm working mainly with embedded systems. In the embedded world, JIT is often simply not an option either because they are not available for your particular target, or because the resource constrains don't allow it. But still you sometimes want to trade resources for ease of development and/or flexibility.
- vardump 11y agoRight, I also do work in embedded (without OS), so I'm familiar with the limitations. However, there are situations where it's tempting to write a very primitive JIT or at least glue pieces of code together in a buffer and execute it, to get good inner loop performance by making it as few instructions as possible. So far C has been enough. Achieving low (=preferably none) defect rate using C is challenging enough. Usually FPGAs can take care of performance critical part. They do increase total cost, though.