6 ms·
Mir: Strongly typed IR to implement fast and lightweight interpreters and JITs
- zer0zzz 3y ago[flagged]
- slimsag 3y agoa proportionate number of times to people leaving comments like this
- pixelpoet 3y agoOn that note, I've seen quite a few zer0s in my time!
- schneems 3y agoIt means peace/world in Russian. He said so in his rubykaigi keynote. Given that, the more peace in this world, the better, I think. I’m curious if he still sees a path or benefit for Ruby switching to such a tool.
- dang 3y ago"Please don't complain about tangential annoyances—e.g. article or website formats, name collisions, or back-button breakage. They're too common to be interesting." https://news.ycombinator.com/newsguidelines.html https://news.ycombinator.com/newsguidelines.html
- zer0zzz 3y agoNoted. Sorry about that.
- 082349872349872 3y agoMIR is a start; someone ought to continue with the following downstream projects: TRYD (Trace Rewriter Yielding Dynamics): reconstitutes a CFG from traces in order to not only JIT single hot paths but also multiple interlacing warm ones MAI (Machine-Agnostic Interpreter): support for mobile processes and agents
- jashmatthews 3y ago> TRYD (Trace Rewriter Yielding Dynamics): reconstitutes a CFG from traces in order to not only JIT single hot paths but also multiple interlacing warm ones Do you have more information on that? Googling didn't turn much up. It sounds similar to the Trace Tree or region based compilation approaches?
- Tiberium 3y agoThat reply is a pun based on the fact that Mir (Мир) means peace in a lot of Slavic languages, and "Мир! Труд! Май!" ("Peace! Labour! May!") was a popular slogan in the USSR for celebrating 1st of May (https://en.wikipedia.org/wiki/International_Workers%27_Day https://en.wikipedia.org/wiki/International_Workers%27_Day)
- 082349872349872 3y agoTiberium is absolutely correct, but I do admit I'd love a TRYD-like project. Thanks for giving me some useful search terms! (to be clear, what I had in mind: not just merging trace heads to form a tree, but merging their tails as well [à la NFA minimisation] to form a cyclic graph; after which one could use region-based techniques on the identified cycles. Rpython's metatracing does a reasonable job for multiple interlacing warm paths, but there's still room for improvement)
- deleted 3y ago[deleted]
- andyferris 3y agoIs the project still active?
- mkleczek 3y agoI think it would be worth mentioning GraalVM and https://github.com/oracle/truffleruby https://github.com/oracle/truffleruby in competitors section.
- charrondev 3y agoLuaJit and PHP both use [DynASM](https://luajit.org/dynasm.html https://luajit.org/dynasm.html) as well.
- binary132 3y agoTIL PHP uses dynasm, here I thought only LuaJIT did. Cool!
- charrondev 3y agoHere’s the RFC for reference https://wiki.php.net/rfc/jit https://wiki.php.net/rfc/jit It passed and landed in PHP 8.0.
- binary132 3y agoI’m surprised their benchmark only saw a 200% performance improvement. LuaJIT is way faster than Lua in many cases.
- charrondev 3y agoSo the PHP implementation was built into the opcache extension which already gives a massive speed up over purely interpreted PHP. If you benchmark JIT PHP vs PHP with no opcache you will see 500% speed up or more depending on the workload. Of course most PHP web servers tend to be pretty IO bound. The project I work on sees ~a 20% in best case response time which is quite nice.
- sparkie 3y agoAdd GNU jitter to the list: https://www.gnu.org/software/jitter/ https://www.gnu.org/software/jitter/
- yawpitch 3y agoAssumed this was about the other MIR: https://llvm.org/docs/MIRLangRef.html https://llvm.org/docs/MIRLangRef.html
- densh 3y agoOf this one: https://rustc-dev-guide.rust-lang.org/mir/index.html https://rustc-dev-guide.rust-lang.org/mir/index.html
- noelwelsh 3y agoLooks like a fun project but I think the window of opportunity might have passed. The Shopify JIT seems to be the way forward for Ruby JITs, and WASM is the obvious choice for new programming languages.
- vidarh 3y agoA new jit (rjit) just landed as an experimental option in 3.3. Ruby is very receptive to trying new things if they look promising.
- viraptor 3y agoAlso rjit is yet-another-jit in Ruby. There's mjit, yjit, rjit, and many external ones. We're getting at least two a year recently, so why not mir as well.
- cozzyd 3y agoToo bad it doesn't support SIMD. Would be nice for an easily embeddable SIMD-aware JIT to exist.
- mike_hearn 3y agoWhat do you mean by easily embeddable? There are JVM JITs that understand SIMD to some extent, and let you write manual SIMD code using the vector API.
- IshKebab 3y agoIt means you can easily use it from another program. Pretty much it has to be written in a language without a runtime that can expose a C interface, i.e. C, C++, Zig or Rust.
- cozzyd 3y agoI guess you can do something like emit code on a memfd, exec ispc to another memfd and dlopen the output but... clunky.
- mike_hearn 3y agoI don't follow. You can load every JITC I know of with C or C++ interfaces. And what is a JITC if not a runtime?
- IshKebab 3y agoThe runtime I'm talking about is for the language that the JIT compiler is written in. If I want to use a JIT compiler that is written in Java in my C++ game I now have to distribute the Java runtime with my game. That's an example of "not easily embeddable".
- mike_hearn 3y agoTwo things here: 1. If by runtime you mean "set of files" you can (these days) compile the Graal JIT compiler to a fully standalone DSO/DLL or even statically link the results into a larger executable. And because the Graal JIT understands Truffle that means making standalone statically linkable JITCs for any language is now very easy. But that said, games always consist of more than one file anyway so the importance of this doesn't seem too high. 2. If by runtime you mean "support code" then C, C++ and Rust all have runtimes so you'd really need to define what specifically you need from a runtime.
- gradschoolfail 3y agoMain takeaway, it avoids SSA Earlier HN discussion 183pts 63 comments https://news.ycombinator.com/item?id=22098399 https://news.ycombinator.com/item?id=22098399 Whats the chance nateb2022? this is way too close (in name) to Lattner’s MLIR to ignore, i thought this morning as I was brushing my teeth. {not to mention LLVM’s own MIR} https://llvm.org/docs/MIRLangRef.html https://llvm.org/docs/MIRLangRef.html
- dibyendu 3y agoSSA is used internally, but the instruction set does not require SSA, if that's what you meant
- gradschoolfail 3y ago“ Using SSA simplifies the optimization implementations, but building and destroying this form is expensive. Using SSA for the MIR generator's short-pass pipeline makes little sense to me, so I don't use it.” In his blogpost.
- pizlonator 3y agoPro jit hacker here. Super cool seeing folks build stuff like this. Thoughts: - great to see an SSA pipeline, but that implies that this jit is not ideal for baseline jiting. That’s fine. I guess I would explicitly call out that although it’s light, it is an optimizer. - which reminds me - a JIT based VM is most defined by how powerful its top JIT is, not how light it is. Maybe since MIR is an optimizer, it’s meant to eventually not be light? It’s generally a bad idea to set out to build a jit, but to then aim in between baseline and full opt. This middle light jits are best built after you’ve evolved your top and bottom tiers (sorta like what happened in V8). - jit IRs need to be given space to evolve to point directly at the user heap, which precludes any kind of reliable serialization. You can dump IR for debugging but you can’t parse IR. This MIR thing is serializable, which would make it an awesome AOT IR. But the serialization code will get in the way once folks try to implement jit based optimizations (like anything speculative). Best to kill the serialization now before it becomes a problem. - if the first front end is C11 then you risk biasing the jit to be very C oriented. Languages that need JIts usually also need weird stuff that C doesn’t need. Super important to test a weirder language. Maybe Lua, since it’s weird but simple. Anyway, this is cool shit. Nice to see people building jits!
- seertaak 3y ago> great to see an SSA pipeline, but that implies that this jit is not ideal for baseline jiting. I'd be interested in knowing the reason -- it's not clear to me tbh.
- noelwelsh 3y agoI assume SSA is too slow.
- pizlonator 3y agoOK, so here's the deal with SSA and the running time of your compiler. - You can convert code to SSA in something like O(N log N) or even close to O(N) if you get fancy enough. The conversion step is not very expensive to run, though it is annoying to implement. Converting to SSA is fine, that's not the problem. - Optimizations implemented on top of SSA are cheap to run. That's sort of the point of SSA. So, that's not the problem. - SSA optimizations achieve goodness when you have multiple of those optimizations running in something like a fixpoint. It's pointless to say "I have SSA" and then just implement one of those optimizations. I don't think MIR does that; like most SSA optimizers, it has multiple optimizations. The problem sort of starts here: SSA sort of implies that you're building an optimizer with multiple optimizations. Even if each opt is cheap, having SSA usually implies that you're going to pile on a bunch of them. So, you'll have cost either from death-by-a-thousand-cuts, or you'll eventually add an optimization that's superlinear. - After your run SSA optimizations, you'll have nontrivial global data flow - as in, there will be data flows between basic blocks that weren't there when you started, and if you do a lot of different SSA optimizations, then these data flows will have a very complex shape. That's caused by the fact that SSA is really good at enabling compilers to "move" operations to the place in control flow where they make the most sense. Sometimes operations get moved very far, leading to values that are live for a long time (they are live across many instructions). This is where the problem gets significantly worse. - Even without SSA optimizations, SSA form adds complexity to the data flow graph because of Phi nodes. You almost always want the Phi and its inputs to use the same register in the end, but that's not a given. This adds to the problem even more. - Probably the reason why you went for SSA was perf. But to get perf from SSA-optimized code, you need to have some way of detangling that data flow graph. You'll want to coalesce those Phis, for example - otherwise SSA will actually pessimise your code by introducing lots of redundant move instructions. Then you'll also want to split ranges (make it so a variable can have one register in one part of a function and a different register in another part), since SSA optimizations are notorious for creating variables that live for a long time and interfere with everything. And then you'll definitely need a decent register allocator. No matter how you implement them, the combo of coalescing, splitting, and register allocation will be superlinear. It's going to be a major bottleneck in your compiler, to the point that you'll wish you had a baseline JIT. Those things I mentioned - coalsce, split, regalloc - are expensive enough that you won't want them in a JIT that is the bottom tier. But they're great to have in any compiler that isn't the bottom tier. So, it's a good idea to have some non-SSA baseline (or template, or copy-and-patch, or whatever you want to call it) JIT, or a decent interpreter, as your bottom tier.
- binary132 3y agoWhen I first read the blog post announcing this project, I got really excited, but unfortunately supporting Windows is not important to the author (correct me if I’m wrong?) and I am mainly interested in projects that are portable between at least windows and Linux, so it isn’t really an option for me.