Earlier quoted context omitted.
Indeed. Most of the hate is due to slow start-up time, but once it gets warmed up, the modern JVM has state of the art dynamic compilation and GC. Thousands of man years have been spent getting it to that point.
With Project Leyden being implemented and JEP 516 coming very soon, those worries will be a thing of the past. Now you can get incredible AOT performance without having to depend on Babashka or GraalVM workarounds.
Jank now has its own custom IR
41–50 of 57 posts
Re: Jank now has its own custom IR
#42Great article, as always. There is one thing that I think is important to bear in mind when discussing inlining, especially in the context of Clojure. This is that once a function has been inlined, you can no longer update the definition of that function in the REPL and have that update the behaviour of functions which use it, unless you recompile those as well. This is not a criticism of course, it’s just part of th…
Right, as you said, you'd have to recompile dependents.
Re: Jank now has its own custom IR
#43Great article, as always. There is one thing that I think is important to bear in mind when discussing inlining, especially in the context of Clojure. This is that once a function has been inlined, you can no longer update the definition of that function in the REPL and have that update the behaviour of functions which use it, unless you recompile those as well. This is not a criticism of course, it’s just part of th…
Re: Jank now has its own custom IR
#44The natural question is why doesn't Jank use MLIR?
Re: Jank now has its own custom IR
#45Hoping to understand this better: > Clojure's dynamism is granted by a great deal of both polymorphism and indirection, but this means LLVM has very few optimization opportunities when it's dealing with the LLVM IR from jank. In my mind, what is happening here is you lower Clojure code into LLVM, with a bunch of runtime calls (e.g. your `jank::runtime::dynamic_call`) (e.g. LLVM invoking the runtime over a C ABI). If…
The article talks about inlining a two-arity call to clojure.core/max to instead be an explicit call to cpp/jank.runtime.max, eliminating the unnecessary argument count matching and recursion portions of the Clojure function. It also mentions that in Clang the runtime max function will itself be inlined, so that's something LLVM ("the LLVM project", anyway) is still doing - and beyond that, as written this IR is like…
> A future optimisation might be to specialise for unboxed types: far more potential speed improvement over pointer tagging, and IMO quite amenable to analysis with the Jank IR
All of these math functions are templates with four specific categories:
1. Object and object
2. Primitive and primitive
3. Primitive and object
4. Object and primitive
We handle the difference between typed objects (like integer_ref) and type-erased objects (object_ref) as well. This template then gets inlined, which is exactly what the last step of the benchmark optimizations (adding annotations) ensured. The return type of these functions will prefer primitive types, rather than automatically boxing. jank's analyzer tracks all types used, at compile-time, and supports automatic boxing. This means that we're already using the most optimal primitive math whenever we can and that it will indeed inline to just an operator call when working on two primitives, or two typed objects, or a combination thereof.
You can see the code for this here: https://github.com/jank-lang/jank/blob/29c2adb344526d26c8e82...
Re: Jank now has its own custom IR
#46Earlier quoted context omitted.
These compilers aren't replacing LLVM, they are adding a compilation step with its own IR where they do certain optimizations and translations *before* handing things off to LLVM. Basically, the idea is to do as much 'high level' optimization and transformation stuff as you can in your own IR, and then let LLVM handle the low-level stuff and the targeting of specific hardware vendors.
That makes sense, thanks. Is this IR at a level where the optimisations can't just be added to LLVM then?
The main thing is that we just use our own IR first, to perform optimizations with contextual data which is gone by the time we get to LLVM IR. That's also why these optimizations are not practical to write in LLVM, since by the time we get to LLVM IR, we're too far separated from jank's AST with the high level semantics of Clojure.
So we just add an intermediate step. Once we have jank's AST, turn it into our own IR, do some optimizations on it for things that LLVM won't be able to see, and then hand it off to LLVM to do the rest.
Re: Jank now has its own custom IR
#47Earlier quoted context omitted.
That makes sense, thanks. Is this IR at a level where the optimisations can't just be added to LLVM then?
I don't know much about Jank's implementation, but I can speak to how it's done in Julia (dynamic, high performance language with lispy semantics but matlaby syntax, JIT compiled to LLVM). I think the big thing is just that LLVM can't really be made to closely model everyone's different weird langauge semantics. In practice, the less C-like your language is, the more hoops you will likely need to jump through in orde…
Despite being a pre-existing feature motivated by C-like languages, typical C/C++ code does not leverage this attribute that much. So there were a surprising number of bugs in the handling of the attribute, and it took a number of years (I didn't follow things closely, but >= 3 for sure, maybe as much as 6?) before they got ironed out enough where it could be enabled.
Re: Jank now has its own custom IR
#48Earlier quoted context omitted.
That makes sense, thanks. Is this IR at a level where the optimisations can't just be added to LLVM then?
As another said, jank is not replacing LLVM or LLVM IR. We still use LLVM IR! There is a diagram here which shows the pipeline: https://book.jank-lang.org/dev/ir.html The main thing is that we just use our own IR first, to perform optimizations with contextual data which is gone by the time we get to LLVM IR. That's also why these optimizations are not practical to write in LLVM, since by the time we get to LLVM IR,…
Re: Jank now has its own custom IR
#49But to be completely honest, the question: "do you need wasm at all...?", should be always followed by "why?". For like 95% of cases, Clojurescript saves you weeks/months of work. Easier to build, easier to maintain. That's subjective, of course. Most Rustaceans don't even want to try Clojure. Most Clojurists find Rust to be needlessly complex.
Re: Jank now has its own custom IR
#50The natural question is why doesn't Jank use MLIR?
I spoke with a couple Clang and LLVM devs about MLIR when I was doing the original design for jank's IR. The general consensus was that MLIR added a great deal of complexity on top of designing/implementing an IR and nobody was confident it was actually worth the effort. Since I knew exactly what I wanted, I just built that.