Relax: JIT compiler for Rust to reduce build times

(makepad.github.io)

166 points | by adamnemecek 1 day ago

20 comments

  • ben-schaaf 8 hours ago
    I did a quick test on various of my rust projects. Most of them it failed to run, on one it miscompiles(?) causing a test case to fail. The only project I got it to run without issue is a basic actix-web website. It takes a whole 14 seconds to actually start the web server. A clean compile is only 24s for all dependencies, and a regular incremental debug build is 2.3s.

    The hot patching is unusable. It takes 11s to compile the patch after a simple change: (Some("hi") -> None), and then relax gets a compiler error when refreshing the page.

    The project where it miscompiles only has a few very basic dependencies; a clean compile takes 1.3s, incremental just 0.25s and tests take ~0.1s. Relax takes a whole 1.4s to run the tests (unsuccessfully).

    • suddenlybananas 6 minutes ago
      I tried it on few projects I have and 2/4 failed to compile. One compiled and ran tests about 20% slower and one compiled and ran tests in the same amount of time as the original.
      • rikarendsmp 4 minutes ago
        I've fixed 100 issues and 50prs over the last 12 hours, any detailed reports welcome
    • rikarendsmp 5 hours ago
      I've been using it successfully for makepads own development iterations for quite some time. This release is the first real outside test. Strange you are getting such wildly different numbers tho.
  • faresahmed 17 hours ago
    Somehow always, someone somewhere rediscovers that cutting down the time between coding and code execution makes our lives easier and to a degree be able to write better programs.

    Perhaps the earliest and best attempt was Lisp's computational model. Since then, the idea manifested itself again[1], again[2], and again[3] in different forms.

    [1]: Inventing on Principle, Bret Victor: https://www.youtube.com/watch?v=PUv66718DII

    [2]: REPL-Driven Development, Stuart Halloway: https://vimeo.com/223309989

    [3]: LIVE, Live Programming workshop: https://liveprog.org/

    • pjmlp 15 hours ago
      Spot on, hence why having a mix of JIT/AOT tooling is such a great experience.

      Besides your examples, Eiffel, Oberon, Java, .NET, C++ (yep even for it), Cedar, Standard ML, OCaml, Haskell, Prolog, BASIC, Forth

    • Capricorn2481 17 hours ago
      This implies that Rust build times haven't been a topic of discussion for the last 10 years. They don't have long build times just for funsies, Rust is completely different from Lisp.
      • christophilus 16 hours ago
        But there's not really a great reason for the long build times. There are plenty of languages that compile very fast. The Rust borrowchecker isn't the source of the bulk of the slowness. It seems to be a combination of language design (e.g. they didn't design it for fast compile times from the start), and implementation decisions. It does seem like there's room for a Rust-like language with Go-like tooling, standard lib, and a focus on development speed.
        • pcwalton 15 hours ago
          It remains to be seen whether you can have a useful borrow checker on top of a simpler type system (at least, a type system that's significantly simpler so as to meaningfully reduce compile times). I have my doubts, personally.
          • brabel 42 minutes ago
            The Goose Programming Language demonstrates an alternative approach that is super simple while being as safe as Rust, or even more if you believe the claim that it doesn’t need unsafe in the language to do anything, unlike Rust.
          • rikarendsmp 13 hours ago
            Relax runs the borrow checker 'lazily' so it already starts your app whilst the borrow checker runs asynchronous. It's jokingly called 'gandalf' because I think It halts the JIT if it finds a problem.
        • treyd 14 hours ago
          The borrowchecker is not the source of the bulk of the language's slowness. It takes a fairly small fraction of the total time, I think I remember the number was 5%-15% depending on the project.

          The majority of time is spent between the trait solver and LLVM optimization passes. There is work being done to improve the trait solver and to produce more efficient LLIR code from the get-go (so LLVM has less to optimize).

          • packetlost 9 hours ago
            Also procmacros add quite a bit of overhead to builds
          • dboreham 8 hours ago
            You always know you're in trouble when you're profiling the compiler and you're just a user of that compiler...
        • imtringued 1 hour ago
          The build times are long because of dependencies and complex but optional features in Rust.

          People should stop abusing the language. Some of my Rust projects compile faster than the time it takes JVM applications to start. Obviously, once the tests are compiled, the test suite with hundreds of tests finishes in less than one second, meanwhile the JVM tests might take 30 seconds.

        • nu11ptr 15 hours ago
          The Rust compiler, while not extremely fast, is not extremely slow either. As an example, my toy compiler is 130K LoC of Rust and compiles in under 7 seconds on a cold build on my M5 Max. An incremental build is nearly instant. So then why is it that so many projects have a minute compile time with far fewer LoC?

          The answer: dependencies (My compiler has virtually none, intentionally)

          Rust has a very small stdlib, so you are forced to bring in dependency crates, and not just a few. Many programs have 50-100 or more, and they all have dependencies, and so on. Contrast with Go where it has a culture of few dependencies, and those project have few dependencies. Your Rust compiler is doing a lot more work for what appears to be the same program as in other langs, but ultimately is a lot more code (typically).

          To make matters worse, cargo does a decent job of parallelizing the builds, but it can only do so a) at the crate level b) only as much as the dependency graph allows.

          • Twirrim 12 hours ago
            I love the language, but I'm still not convinced by Rust's skinny stdlib approach. I appreciate not wanting to end up like python where they're having to remove stuff from the stdlib because it has too many batteries and bitrot is a problem, but there's surely a happy-medium somewhere along the line.

            I don't write much Go but it seems like it has a good balance when I do.

            It may be a bad example, but even in rust generating a random number involves pulling in 6ish crates

               └── rand v0.10.3
                ├── chacha20 v0.10.2
                │   ├── cfg-if v1.0.5
                │   └── rand_core v0.10.1
                ├── getrandom v0.4.3
                │   ├── cfg-if v1.0.5
                │   ├── libc v0.2.191
                │   └── rand_core v0.10.1
                └── rand_core v0.10.1
            • coderenegade 10 hours ago
              The skinny stdlib is always a mistake imo, because if you don't provide it, somebody else will, and it's unlikely to be as nice to work with for your users as a standard library implementation. In the case of C++, for instance, this lead to the boost era.

              For all of Python's warts, it at least makes everyday structures and operations you might want to use fairly painless, and it keeps expression fairly standardized. Leave external libraries to build things that are actually interesting, rather than scaffolding and infrastructure that the language vendor is better off providing.

              • imtringued 58 minutes ago
                >The skinny stdlib is always a mistake imo, because if you don't provide it, somebody else will, and it's unlikely to be as nice to work with for your users as a standard library implementation. In the case of C++, for instance, this lead to the boost era.

                I disagree, skinny stdlib is an option that you intentionally leave open. You let the ecosystem around you explore good solutions first before you commit early or exhaust the air in the room for better ideas.

            • nu11ptr 11 hours ago
              Agreed. I would like to see an extended stdlib of sorts form perhaps taking inspiration from Go or Python. I think it is too late to shim it into the language itself, but it could be like an alternative stdlib of sorts (more like an addendum, not replacing what is already in stdlib). The bonus is it would be precompiled for all platforms so even if doing a cold compile, it just is linked.
            • cmrdporcupine 11 hours ago
              100% this. Was playing with the odin language recently (https://odin-lang.org/) and was very pleased at what was included in the std lib while still being a good viable systems PL. And delightful fast compilation time.

              That said, I missed the borrow checker.

              • pjmlp 9 hours ago
                And a certain Object Pascal feel to it, while the provided library is not on the same vein as MacApp, Turbo Vision, or OWL.
          • mpweiher 3 hours ago
            > The answer: dependencies

            Assuming for a second this is true.

            Why?

            We solved separate compilation a few decades ago. So if those dependencies are causing your compile times to spiral out of control, then something is wrong.

            For example unlearning separate compilation, as we seem to have done.

          • shikck200 7 hours ago
            > M5 Max

            Fucking lol. I have an almost decade-old laptop and compile projects way faster. Ocaml and Go both compile 100K LOC projects under 1sec.

            • pjmlp 5 hours ago
              That is what I always point out, not everyone on the planet can afford the kind of hardware that makes Rust builds usable, thus it is a potential loss of users that are then pushed into adopting languages that are friendlier in hardware requirements.

              And to make a point, the Turbo Pascal 5.5 compilation times, from 1989 marketing brochure

              > Fast! Compiles 34 000 lines of code per minute

              This was measured on a IBM PS/2 Model 60, a computer model from 1987, with a 80286 running at 10 MHz, limited by 640 KB, with luck one would expand it up to 1 MB and use HMA, in what concerns using it with MS-DOS.

              You can get the brochure at https://archive.org/details/bitsavers_borlandtur5.5Brochure1...

              So one would expect that at very least for debug builds in 2026, one would always have blazing fast build times.

              Which is why languages like OCaml, Go, Zig, D, Delphi and co, are not doing something spectacular, rather pretty much what should be the norm, and unfortunately got sidetracked somehow.

      • pjmlp 15 hours ago
        Haskell, Standard ML and OCaml have the tools for faster development workflows, or going for lunch while producing an optimised build.

        It is a matter of priorities.

      • faresahmed 16 hours ago
        I beg to differ. It's not that Rust is completely different from Lisp. PL writers get so caught up with their 'killer feature' which in the case of Rust is the borrow checker, that they completely abandon the other 50% which is the environment.

        If we stopped treating the compiler as a one-shot program, we could theoretically shorten this edit-build-test loop by 99%.

        • shikck200 7 hours ago
          Rust's killer features is not "the borrow checker". That idea was just stolen from Cyclone. Rust is basically a semi ml kind of language in the c++ space. I dont see many "killer features" in rust outside the saner type system.

          Its basically a better language for software you write in C at the cost of horrible compile times.

          • brabel 36 minutes ago
            The killer feature is definitely memory safety in a systems programming language. That was pretty much thought impossible before Rust came along, and even today there is essentially no competition offering both memory safety and C performance, which requires no GC really.
        • LoganDark 16 hours ago
          The borrow checker is an example of a certain kind of reasoning that Rust benefits from. There's a reason a Lisp can be inspected and rewritten as the process runs, and it's the same thing that makes Rust difficult to rewrite in the same way. Not sure the exact term for it, but it's very easy to have profound nonlocal effects, for example with TAIT (type alias impl trait).
          • wahern 16 hours ago
            The borrow checker doesn't rely on interprocedural analysis. The function prototype provides all the information needed to maintain lifetime invariants across functions, so given static typing already then interprocedural borrow checking is effectively zero cost at compile time. (Cf. Intraprocedural, non-lexical borrow checking.) So borrow checking is no impediment to dynamically replacing function definitions. And it would be less of a headache for intraprocedural REPL but-for non-lexical semantics. But in a REPL you could always use an interpreter for running a function currently being edited, then compile it down once complete. REPLs are a headache for languages like Rust because of static typing generally, generics, trait semantics, etc.
          • pjmlp 5 hours ago
            The reason is tooling matters, you can also do the same in C++, tools do exist.
        • Ar-Curunir 14 hours ago
          rustc is not really a one-shot program! Incremental computation is a big part of rustc !
  • _cart 14 hours ago
    Pretty wild to me that AI has enabled the commoditization of one of the gnarliest engineering problems. Over the course of just a month, we now have three "viable" AI-driven iteration-focused Rust compilers: - https://github.com/makepad/relax - https://github.com/DioxusLabs/rustd/ - https://github.com/indexable-inc/blaze
    • medler 11 hours ago
      The Cranelift compiler is in the same space, has been around for over a decade, and is actively maintained: https://en.wikipedia.org/wiki/Cranelift
      • zamadatix 10 hours ago
        I'm not sure the Rust JIT feature looks far enough along/well maintained enough to actually work with a typical rust program and when it does it sounds like it's probably slower than AOT anyways https://github.com/rust-lang/rustc_codegen_cranelift/blob/ma...

        I think it also only does the backend? I.e. you still need rustc to compiler to do everything but the codegen whereas this seems to be the whole compiler portion of the toolchain "Relax isn't a wrapper around rustc or a plugin for LLVM: it replaces both, and the parts of Cargo and the linker in between."

      • shikck200 7 hours ago
        Cranelift never took off. Its weirdly bundled inside some adhoc wasm runtime, and is not a replacement for the "real" rust compiler.
        • uqers 7 hours ago
          Doesn't cargo nightly ship with the cranelift backend? You do need to mess with rustup and cargo a bit, but it's not very difficult to use.
      • theknarf 2 hours ago
        blaze uses Cranelift under the hood, I'm not sure about the other two.
    • 392 12 hours ago
      I'd like to throw my low-token-budget hat in the ring:

      https://github.com/haydenflinner/rust/blob/main/PLIRON.md

      iteration-focus is slightly there, i.e. fast hotpatching. But been focused on beating LLVM's compiled runtime performance as of late.

    • steveklabnik 7 hours ago
      I’ve got one I haven’t made public yet as well…
    • anonymous908213 12 hours ago
      "Viable" in scare quotes, as it should be. Note that the third one you listed is forked from the second one with licensing credit stripped. None of them are actually used by anybody programming anything real. Calling this commoditization is ridiculous. Commoditization of being able to post superficially impressive claims that get upvoted to the front of HN while drowning out content that has >0 value to anyone on the planet, I suppose.
      • _cart 7 hours ago
        I'll note that I _am_ also dubious of the lifespan / long term viability of these projects (easy come, easy go), and I agree that they're very rough / early stages right now. That being said, I'm not writing off their value either. I've played with all of them, and while they aren't bulletproof (I haven't managed to get Bevy to actually run with any of them), they are undeniably close to being viable.
  • Sytten 17 hours ago
    We have had good experience with kache so far to speedup builds in CI and local
    • n_u 17 hours ago
      How does it compare to sccache ?
      • jtwaleson 16 hours ago
        Kache caches more, and is path independent, so can be shared between worktrees.
        • aabhay 12 hours ago
          Sccache has base dir support now. But you have to be vigilant about not including things like cargo manifest dir
        • TheMrZZ 14 hours ago
          Interesting. First time I hear about Kache, I'm definitely gonna give it a try.
  • jkelleyrtp 16 hours ago
    I built something similar - tbd on maintaining it - but I got Rust Analyzer emitting code and as well as running in the web. This new concept of rust compile daemon is pretty sick.

    Can build and iterate on Rust in the browser!

    https://dioxuslabs.github.io/rustd/

  • cedws 13 hours ago
    Rust is a nice language but it’s so heavy. Since our company switched from Go I’ve had to become used to my laptop being burning hot and stuttering whilst trying to do anything during compilation.
    • TakerofVita 9 hours ago
      yeah, I've been doing some game dev with rust, and the cost of iteration is hugely higher (though it has been worth it so far). Often a build takes 10min+. Something like this project would help a lot if it supported windows.

      It is pretty noticeable if you have agents working in subtrees too, a fresh build in a worktree can be like 20min with bevy

      • _cart 7 hours ago
        Bevy (the engine itself) actually compiles faster than Godot (the engine itself) on my machine. The difference is that Godot ships the engine pre-compiled. With cached builds / shared builds (and/or dynamic linking) things look much better. (disclosure: I am Bevy's creator). That being said, if you're doing GDScript for game logic (or even C#) in Godot, game logic does still compile much faster in Godot. And the "precompiled Bevy / dynamic linking game logic" pattern in Bevy isn't a standard workflow atm (but with the upcoming editor we're planning on making that easier to set up).
      • cedws 3 hours ago
        It doesn’t have to be like this though. Jonathon Blow’s new game compiles at a crazy speed, like under 5s IIRC.
        • jakkos 1 hour ago
          Afaik those speeds are only unoptimized non-llvm builds, and the things that make rust compile times slow are llvm and things Jai doesn't do like traits and monomorphization
    • LtdJorge 7 hours ago
      You can limit the threads
    • evulhotdog 12 hours ago
      I’d gladly accept that for the efficiency and speed gained in prod, knowing I need to have a beefier host to compile it.
    • pjmlp 5 hours ago
      If Go devs were more welcoming to 1970's programming language research, there would be even less reasons to use Rust.

      Many folks reach for it, because it is the only ML like language that they are aware of, and not necessarily due to the borrow checker.

      On the other hand, Rust could have by now, the same kind of interpreters/JIT alternative implementations that OCaml, Standard ML, F#, Scala, Haskell enjoy, some of them for at least 30 years.

      • imtringued 49 minutes ago
        I'm curious. Is there anything stopping someone from building a Rust to Go compiler?
  • kennykartman 1 day ago
    I knew that makepad devs were focused on build times, but didn't imagine this much!
    • rikarendsmp 13 hours ago
      Indeed but I could only do this in the age of AI. Before a project like this was just out of reach.
  • knuckleheads 1 hour ago
    After working on https://github.com/PowderworksCode/headstart and some good conversations with the compiler team, I've been working on finding a way to make big changes to speed up rust while also respecting their wishes around the usage of LLM's. I don't really want to support a vibe slopped fork of rustc/cargo that is full of patches that are pretty much immediately out of date, and I don't think anyone else does either, at least not in a long term dependable way. I also don't feel like recreating daemons from the ground up, I would rather build on top of what already exists and make that compile faster and have better performance.

    https://breakneck.powderworks.dev/

    It's not done yet nor do I have enticing numbers to show, but I think in a few weeks Breckneck Rust will be someplace nice. For big changes such as getting all crates in the same process, I've been having Claude develop and use a mass static code rewriting tool. So instead of having an agent go and found all the places where LOCAL_CRATE_ID is defined and used, a query finds it and then rewrites can target it and it's surroundings.

    My hope is that mass code rewrites are more acceptable to the compiler team, in that they can author, review and debate the rewrites ahead of time without any time pressure. Listening to the team, there were things they might want to do/try (dropping memory, all crates in one process), but the changes are so comprehensive that to do them by hand is effectively a stop the world process. With mass code rewriting tools, it should be possible to rerun the rewrite on main whenever, and as well, any work that others have going on in pr's can likewise be transformed without any impact. This way takes a bit of coordination, but not years and years of it.

    Similarly, it's not clear that any of the big changes are actually worth it yet. Maybe dropping memory is a meh, or compiling all the crates at once is not that big a win. I can run this on nightly and keep up to date with what's going on there while experimenting with weird stuff, without wandering out into the wilderness with a hard fork. Maybe there's a way to 100x perf on the other side, and if a pathway can be shown to get there in theory via agents, then the team can find their own path there that fits their attitudes around use or none use of agents and we all benefit. Exciting times!

  • scottmas 15 hours ago
    Anyone know what effect it has on targets/ bloat and dev disk usage?
    • rikarendsmp 13 hours ago
      It should be lower, but I haven't optimized it too hard on disk size. It's about iteration latency for LLM's.
  • jonstewart 16 hours ago
    I've been using "mr boxington" (mbx) the past several weeks and it's been a big help. https://mr-boxington.jdx.dev/
  • ricardobeat 14 hours ago
    > 0 crates.io dependencies, in 438k lines of Rust

    It's great to have zero deps, but that's a lot of code to maintain.

    • rikarendsmp 13 hours ago
      AI maintains it, and its developer tooling really. The main use case is hotloading for LLM's to reduce wait-for-result time and to allow applications other be hot-debugged. Pause on panic is one of its main features I use all the time.
      • brabel 30 minutes ago
        Pause on panic? Nice like Common Lisp, can you fix the code and then resume from the beginning of the function like in Slime?
  • ylisav 3 hours ago
    Are we inventing python from first principles?
  • rfgplk 2 hours ago
    I'd genuinely suggest most people get into the business of writing custom compilers. You have no idea how poor the common implementations are. My from scratch Rust compiler outright outperforms rustc by lowering comptimes by around 80%, while maintaining bitexact binaries (verified on millions of LoC && formally verified).
  • Surac 16 hours ago
    moving errors from compile time to runtime is good?
    • masklinn 1 hour ago
      The errors part of compilation is `cargo check` and that’s usually (though not always!) a fairly small amount of the total. Codegen is where the compiler usually spends most of its time.
    • jtwaleson 16 hours ago
      For some use cases, like speeding up local development, it's an excellent trade off.
    • andix 15 hours ago
      For quick iterations it's perfectly fine. Change something, see if it works. If it doesn't keep changing until it works.

      In runtimes that provide quick dev loops some developers have continiously running unit testing sessions. They just fire off every few seconds and give intimidate feedback.

    • rikarendsmp 13 hours ago
      It's a technology to improve iteration time with agents, or humans for live coding but nobody really writes code anymore so.
  • ridiculous_fish 16 hours ago
    This is preposterously ambitious - a complete Rust re-implementation. Looks like it's mostly claude?
    • pcwalton 15 hours ago
      Yeah, this is pretty much a textbook example of what AI agents make possible these days: things that are ridiculously ambitious, but aren't conceptually very difficult (or, at least, are conceptually well-trodden ground). Things like emulators, language runtimes, platform reimplementations like Darling, etc.

      JITting Rust isn't conceptually very hard: you just take rustc and make everything dynamic instead of static. The only thing that was stopping it before was the sheer amount of effort. Well, now we have a way to reduce that effort.

    • rikarendsmp 13 hours ago
      Yea it's claude+codex over the course of a month. It definitely isn't a one shot.
  • tontinton 17 hours ago
    The world really needs something like this, but why such a slop UI website.

    Just tell Opus 5.5 to "redesign the UI to not look like AI slop, design it like a human expert designer would" at bare minimum.

    • rikarendsmp 13 hours ago
      Its only prompt is 'make a flashy website for this project'. I think it's fine who reads websites anymore anyway. Readme.md for GitHub is the main thing.
    • hn_submit 14 hours ago
      The code is slop and the website too.
    • poly2it 15 hours ago
      Perhaps a cynical take, but I feel sloppy content advertised seriously is enabling a transparent form of cross-domain self-selection which can be interesting to observe from the outside.
  • baq 15 hours ago
    Common Lisp lurks in the shadows, watching its own reinvention comfortably, yet another time
  • samblob1 4 hours ago
    Every commit is vibed lol. absolutely no way.
  • measurablefunc 10 hours ago
    Nice project.
  • joshsyn 12 hours ago
    [dead]