Stream: announcements

Topic: build times survey


view this post on Zulip Richard Feldman (Aug 04 2026 at 21:39):

I'd like to get some numbers on what kind of build times people are seeing when building things with Roc.

This is very open-ended! I'm just trying to get a sense of what people are seeing in practice, since I care a lot about build times being fast but since I'm focused on compiler work right now, I don't have a sense of what people are experiencing on their projects. :smile:

Feel free to post any numbers you have in this thread! It's helpful to know if they're cold builds (--no-cache) or rebuilds, and also ideally what system you're running on and what roc version outputs.

view this post on Zulip Niclas Ahden (Aug 04 2026 at 21:49):

Building Joy TodoMVC:

roc build --target=wasm32 --no-cache app.roc

roc build
  ✓ Resolving Dependencies       484ms
  ✓ Parsing                      8ms
  ✓ Name Resolution              3ms
  ✓ Type Inference               50ms
  ✓ Compile-Time Evaluation      3ms
      Monotype Lowering          1ms
      LIR Generation             0ms
      LIR Passes                 0ms
      ARC                        0ms
      Static Data                0ms
      x64 Instruction Generation 0ms
      Execution                  1ms
      Store Results              0ms
  ✓ Monotype Setup               0ms
  ✓ Root + Wrapper Setup         0ms
  ✓ Specialization Lookup + Reservation 1ms
  ✓ Dispatch Evidence            5ms
  ✓ Body Graph Setup             6ms
  ✓ Body Traversal + Binding     58ms
  ✓ Body Type Graph              0ms
  ✓ Body Call Dispatch           0ms
  ✓ Body Draft IR Construction   0ms
  ✓ Body Reachability + Proofs   0ms
  ✓ Body Source Mapping          0ms
  ✓ Body Local Procedure Context 0ms
  ✓ Body Sealing + Commit        5ms
  ✓ Procedure Completion         0ms
  ✓ Layout Requests              0ms
  ✓ Static Data Requests         0ms
  ✓ Monotype Finalization        0ms
  ✓ Closure Lifting              0ms
  ✓ SpecConstr                   15ms
  ✓ Lambda-Set Solving           7ms
  ✓ Inline Planning              0ms
  ✓ LIR Generation               1ms
  ✓ LIR Passes                   2ms
  ✓ ARC                          1ms
  ✓ Static Data                  0ms
  ✓ LLVM IR Generation           6ms
  ✓ LLVM Optimize + Emit         406ms
  ✓ Linking                      7ms
roc build                   1.1s
0 errors and 0 warnings found in 1.1s while successfully building:

    app.wasm

Edited source with cache:

roc build --target=wasm32 app.roc

0 errors and 0 warnings found in 552ms while successfully building:

    app.wasm

NixOS, x86, AMD 9950X, Roc 94cbed386c51a8739ced3be76e7ab7b84dd22852.

view this post on Zulip Jasper Woudenberg (Aug 04 2026 at 22:06):

Check and test times too? Test times in particular I noticed are a bit on the slower side, especially for the relatively small number and libraries I run these for.

Using Roc build from nix flake, revision 38c51448b837ae3fd1b606805ef2b254b196596e

# roc check --no-cache rvn/main.roc
No errors found in 627ms for main.roc

# roc test --no-cache rvn/main.roc
All (82) tests passed in 9832.2 ms.

# roc check --no-cache gregorian/main.roc
No errors found in 501ms for gregorian/main.roc

# roc test --no-cache gregorian/main.roc
All (48) tests passed in 4508.5 ms.

view this post on Zulip Richard Feldman (Aug 04 2026 at 22:08):

those test times are very surprising! I'll look into that, thanks :+1:

view this post on Zulip Luke Boswell (Aug 04 2026 at 22:23):

Linux x64 AMD Ryzen 7 9700X 8-Core Processor

Screwbot on a gaming rig

view this post on Zulip Luke Boswell (Aug 04 2026 at 22:27):

Makes me think we should add a flag for build times in a machine readable format like JSON

view this post on Zulip Karl (Aug 05 2026 at 00:34):

| $ roc build --output="./bt" --opt=speed apps/burntranscribe/main.roc
roc build
  ✓ Resolving Dependencies       3ms
  ✓ Parsing                      9ms
  ✓ Name Resolution              18ms
  ✓ Type Inference               295ms
  ✓ Compile-Time Evaluation      1.2s
      Monotype Lowering          1.1s
      LIR Generation             78ms
      LIR Passes                 2ms
      ARC                        3ms
      Static Data                1ms
      arm64 Instruction Generation 11ms
      Execution                  11ms
      Store Results              1ms
  ✓ Monotype Setup               0ms
  ✓ Root + Wrapper Setup         0ms
  ✓ Specialization Lookup + Reservation 8ms
  ✓ Dispatch Evidence            0ms
  ✓ Body Graph Setup             37ms
  ✓ Body Traversal + Binding     785ms
  ✓ Body Type Graph              0ms
  ✓ Body Call Dispatch           0ms
  ✓ Body Draft IR Construction   0ms
  ✓ Body Reachability + Proofs   0ms
  ✓ Body Source Mapping          0ms
  ✓ Body Local Procedure Context 0ms
  ✓ Body Sealing + Commit        590ms
  ✓ Procedure Completion         2ms
  ✓ Layout Requests              0ms
  ✓ Static Data Requests         0ms
  ✓ Monotype Finalization        0ms
  ✓ Closure Lifting              1ms
  ✓ SpecConstr                   854ms
  ✓ Lambda-Set Solving           209ms
  ✓ Inline Planning              0ms
  ✓ LIR Generation               27ms
  ✓ LIR Passes                   287ms
  ✓ ARC                          72ms
  ✓ Static Data                  0ms
  ✓ LLVM IR Generation           1.4s
  ✓ LLVM Optimize + Emit         10.0s
  ✓ Linking                      285ms
roc build                   15.9s

Same timings with --no-cache on the second run. App is 3.5k LoC, Platform is 3k LoC Roc + 71k LoC Rust, Macbook M1

view this post on Zulip Karl (Aug 05 2026 at 00:39):

$ roc build --no-cache --output="./bt" --opt=speed examples/realworld/main.roc
roc build
  ✓ Resolving Dependencies       3ms
  ✓ Parsing                      6ms
  ✓ Name Resolution              8ms
  ✓ Type Inference               105ms
  ✓ Compile-Time Evaluation      12ms
      Monotype Lowering          5ms
      LIR Generation             2ms
      LIR Passes                 0ms
      ARC                        1ms
      Static Data                0ms
      arm64 Instruction Generation 1ms
      Execution                  2ms
      Store Results              0ms
  ✓ Monotype Setup               0ms
  ✓ Root + Wrapper Setup         0ms
  ✓ Specialization Lookup + Reservation 3ms
  ✓ Dispatch Evidence            4ms
  ✓ Body Graph Setup             12ms
  ✓ Body Traversal + Binding     258ms
  ✓ Body Type Graph              0ms
  ✓ Body Call Dispatch           0ms
  ✓ Body Draft IR Construction   0ms
  ✓ Body Reachability + Proofs   0ms
  ✓ Body Source Mapping          0ms
  ✓ Body Local Procedure Context 0ms
  ✓ Body Sealing + Commit        43ms
  ✓ Procedure Completion         1ms
  ✓ Layout Requests              0ms
  ✓ Static Data Requests         0ms
  ✓ Monotype Finalization        0ms
  ✓ Closure Lifting              2ms
  ✓ SpecConstr                   54ms
  ✓ Lambda-Set Solving           56ms
  ✓ Inline Planning              0ms
  ✓ LIR Generation               137ms
  ✓ LIR Passes                   92ms
  ✓ ARC                          27ms
  ✓ Static Data                  1ms
  ✓ LLVM IR Generation           641ms
  ✓ LLVM Optimize + Emit         5.1s
  ✓ Linking                      96ms
roc build                   6.6s

Example is 1.2k LoC, platform is 1.3k LoC

view this post on Zulip Richard Feldman (Aug 05 2026 at 00:51):

@Karl @Jasper Woudenberg @Niclas Ahden out of curiosity, do you normally use roc build when building for development? or do you use roc without build to just build and run? or something else?

view this post on Zulip Karl (Aug 05 2026 at 00:56):

I've been using the CLI as listed without the --no-cache just because 5-15s doesn't really bother me (Rust...) but I mean to switch over to just running it in roc for the hot reload. I haven't done it yet because it's not picking up the changes. I think it's the main loop not terminating and it'll work if I tweak it but I haven't gotten around to it. I've been very platform focused on both projects so I haven't been doing a lot of app work and that would change the motivation.

The 7min timing for rebuilding the Roc compiler (which is like 5:50 LLVM) does annoy me but that's a matter of Apple silicon getting zig incremental builds.

view this post on Zulip Richard Feldman (Aug 05 2026 at 01:10):

ok maybe we should change the default...roc build is actually doing optimized builds, which is not necessary - if you do roc build --opt=dev it will not use LLVM and will be way faster

view this post on Zulip Richard Feldman (Aug 05 2026 at 01:11):

the reasoning for making --opt=speed the default for roc build was the assumption that roc without build would be used for normal development, and once you wanted to do roc build it was probably because you were ready to actually release, so it would be helpful to make it so you couldn't forget to do --opt=speed but maybe that's actually not the right default after all :sweat_smile:

view this post on Zulip Karl (Aug 05 2026 at 01:17):

I think that was the right decision. I do it this way because I run compiled languages in release unless it's slow enough to really disrupt things and I'm not annoyed to the point of making the change. As mentioned, I do plan on switching over to the base roc for dev once I figure out why the hot reload isn't getting picked up on my platforms which is my issue and not roc.

view this post on Zulip Richard Feldman (Aug 05 2026 at 01:35):

oh you shouldn't need to do anything

view this post on Zulip Richard Feldman (Aug 05 2026 at 01:37):

it might be the way it's structured though - basically what happens is that when roc detects a change to the entrypoint function(s) your app provides to the platform, it just swaps them out for the new ones so that the next time the platform calls them, it'll get the new ones

view this post on Zulip Richard Feldman (Aug 05 2026 at 01:37):

so if you're not seeing any hot loading, I'm guessing it's because the platform only calls those functions once on startup?

view this post on Zulip Karl (Aug 05 2026 at 01:38):

They're both on an event loop so I think I have to trampoline the loop or something.

view this post on Zulip Richard Feldman (Aug 05 2026 at 03:17):

does the event loop call them repeatedly? :thinking:

view this post on Zulip Jasper Woudenberg (Aug 05 2026 at 07:11):

Richard Feldman said:

Karl Jasper Woudenberg Niclas Ahden out of curiosity, do you normally use roc build when building for development? or do you use roc without build to just build and run? or something else?

I haven't used roc build much yet because I've been working on libraries. Now I'm back to working on my platform jay, there I don't expect to use roc build much either because the nature of jay is that you run it as a script.

view this post on Zulip Niclas Ahden (Aug 05 2026 at 08:15):

Richard Feldman said:

the reasoning for making --opt=speed the default for roc build was the assumption that roc without build would be used for normal development, and once you wanted to do roc build it was probably because you were ready to actually release, so it would be helpful to make it so you couldn't forget to do --opt=speed but maybe that's actually not the right default after all :sweat_smile:

I’m using it exactly as you describe, so I’m happy with the current situation :ok:

view this post on Zulip Richard Feldman (Aug 05 2026 at 12:18):

ok then I'll leave it as-is for now!

view this post on Zulip Niclas Ahden (Aug 05 2026 at 12:35):

Tested on a Mac:

MacBook Pro M1 Max: Full TodoMVC build

MacBook Pro M1 Max: build --watch on a small change

view this post on Zulip Richard Feldman (Aug 05 2026 at 12:39):

nice!

view this post on Zulip Bryce Miller (Aug 06 2026 at 01:03):

Here's an example from roc-pg:

Roc version: nightly-2026-August-05-24f0b47
Source: https://github.com/sandprickle/roc-pg/blob/migrate-zig-compiler/examples/query.roc
MacBook Air M1

HyperFine output

roc build output

Dev build is just a hair over 700ms

view this post on Zulip Krzysztof Skowronek (Aug 13 2026 at 21:21):

I built the robot arm example on Windows on Thinkpad T14 with Ryzen 7 PRO 4750U

38.7s for --no-cache

31.4s with cache

opt=dev 12s, but it crashes

also, the program itself takes 120mb of RAM, I don't know if that's a lot to be honest, but it seems quite a bit for a raylib app. When I wiggle the arm fast, it grows to above 200 sometimes. I wanted to take a screenshot, but now it just hovers around 130-140 no matter what I do :)

view this post on Zulip Krzysztof Skowronek (Aug 13 2026 at 21:22):

so I don't think that the cache is doing much on Windows, and the compile times are a bit long for my taste - I hope that's just a quirk of the almost numbered version :)

view this post on Zulip Krzysztof Skowronek (Aug 13 2026 at 21:33):

https://github.com/lukewilliamboswell/terrocotta/blob/screwbot-showcase/examples/counter.roc

roc --opt=dev .\examples\counter.roc takes 3s, almost 18s for the speed build

view this post on Zulip Krzysztof Skowronek (Aug 13 2026 at 21:35):

also, the counter app itself uses 70mb of ram, which is more in line of what I would expect - C# and WPF app with a counter would probably stay under 30mb though

view this post on Zulip Luke Boswell (Aug 13 2026 at 21:41):

Thank you @Krzysztof Skowronek would you mind sharing roc version

view this post on Zulip Krzysztof Skowronek (Aug 13 2026 at 21:45):

PS C:\Users\KrzysztofSkowronek> roc --version
Roc compiler version nightly-2026-08-12-606470f

view this post on Zulip Krzysztof Skowronek (Aug 13 2026 at 22:26):

counter.cs
counter_winforms.cs

out of curiosity I made a counter example in C#, if you want you can run it with dotnet run -c release counter.cs (only on Windows)

wpf version uses 60mb, winforms is 10mb :D

view this post on Zulip Richard Feldman (Aug 13 2026 at 23:14):

thanks, I'll take a look at these!

view this post on Zulip Richard Feldman (Aug 13 2026 at 23:17):

I'm surprised lss and monotype lowering are taking so long. The linking thing should be an easy fix.

view this post on Zulip Aurélien Geron (Aug 16 2026 at 09:31):

FWIW, here's the execution time of 110 exercises using roc test --opt=dev versus roc test --opt=speed. I had to use a log-log scale because the timings vary wildly. There are a few outliers on both sides:

image.png

Since I'm using roc test, this includes both the build time and the execution time.

view this post on Zulip Richard Feldman (Aug 16 2026 at 11:20):

which ones are the outliers? I can look at those first

view this post on Zulip Aurélien Geron (Aug 16 2026 at 20:24):

Thanks @Richard Feldman . Here are the exercises that take over 1 second with --opt=speed and that are over 20 times slower than with --opt=dev:

Note: the exercises that are much slower with --opt=dev than with --opt=speed are the compute-heavy exercises, so it makes sense, no issue there.

Lastly, there are two exercises that work fine with --opt=dev but crash with --opt=speed: robot-name and pov.

view this post on Zulip Richard Feldman (Aug 16 2026 at 20:26):

I'm curious about the compute-heavy ones too, actually!

view this post on Zulip Aurélien Geron (Aug 16 2026 at 20:28):

Sure, here they are:

view this post on Zulip Aurélien Geron (Aug 16 2026 at 20:34):

Here's the full table if you're interested:
dev_speed_comparison.tsv

view this post on Zulip Richard Feldman (Aug 16 2026 at 21:11):

nice, thank you! I'm gonna dig into these and see what room for improvement there is

view this post on Zulip Richard Feldman (Aug 16 2026 at 21:11):

if you're curious to try it, the --specialize=no flag is an experimental thing that may help with roc test times specifically

view this post on Zulip Richard Feldman (Aug 16 2026 at 21:12):

might also make them worse right now though, not sure :laughing:

view this post on Zulip Aurélien Geron (Aug 16 2026 at 21:55):

I tried --specialize=no with roc test, but I got a lot of crashes, and a few freezes:

view this post on Zulip Aurélien Geron (Aug 16 2026 at 21:57):

The execution times for the ones that worked are a bit suspicious, with a vast majority equal to 130.1 ms:

view this post on Zulip Aurélien Geron (Aug 16 2026 at 22:51):

One last thing: for two exercises, roc test --opt=speed crashes while roc test --opt=dev works fine. I'm trying to reproduce the issue with a minimal code example, but it's not easy.

view this post on Zulip Luke Boswell (Aug 17 2026 at 04:05):

I've got some really fat apps in the roc-pdf package... I'll do a more structured survey and share the results here.

view this post on Zulip Luke Boswell (Aug 17 2026 at 05:03):

All the results and configuration is in this JSON file, and I included an analysis also from codex

https://gist.github.com/lukewilliamboswell/07b088aebb7d1ec25fa663f0800c06eb

image.png

view this post on Zulip Luke Boswell (Aug 17 2026 at 05:04):

This is using yesterday's nightly

view this post on Zulip Luke Boswell (Aug 17 2026 at 05:58):

roc build tests/gate3_pdf_facade_chunks_negative/main.roc --opt=dev

view this post on Zulip Aurélien Geron (Aug 24 2026 at 02:41):

Something is a bit fishy with the speed of roc test --opt=dev. Here's a graph comparing the test time last week (August 16 in NZ) with the test times today (August 24 in NZ) across all Exercism exercises:

image.png

Notice that the times are comparable above 100ms (although a bit higher today than last week), but there's no longer any test time below roughly 130ms.

view this post on Zulip Aurélien Geron (Aug 24 2026 at 02:52):

Here's the same graph but with --opt=speed (for both dates).

image.png

Edit: I updated the graph because I had made a mistake. Fixed now.

view this post on Zulip Aurélien Geron (Aug 24 2026 at 02:57):

Lastly, here's --opt=dev versus --opt=speed today:

image.png

This looks significantly worse for most exercises, except 5.

view this post on Zulip Luke Boswell (Aug 24 2026 at 03:20):

How are you collecting the time, is this time roc test ...?

view this post on Zulip Luke Boswell (Aug 24 2026 at 03:21):

Definitely smells like a regression somewhere is putting a floor on the test time. My guess is we broke the caching for the builtins somehow (totally wild guess)

view this post on Zulip Aurélien Geron (Aug 24 2026 at 03:35):

I'm just grabbing the times displayed in the test outputs, such as: All (14) tests passed in 1032.6 ms.

view this post on Zulip Luke Boswell (Aug 24 2026 at 03:43):

Another example of where we should add that machine readable output flag ... did we ever make a GH Issue for that?

view this post on Zulip Luke Boswell (Aug 24 2026 at 03:43):

I'll have a look

view this post on Zulip Luke Boswell (Aug 24 2026 at 03:54):

Is there a better format for machine readable stats than JSON?

view this post on Zulip Luke Boswell (Aug 24 2026 at 03:54):

Oh ... sqlite3? :grinning_face_with_smiling_eyes:

view this post on Zulip Luke Boswell (Aug 24 2026 at 03:55):

Now we're cooking with gas

view this post on Zulip Aurélien Geron (Aug 24 2026 at 04:01):

Btw, the two exercises that used to crash with --opt=speed but not with --opt=dev now work fine with both. However, the sgf-parsing exercise now causes a segfault when run with --opt=speed, I opened issue #10912.

view this post on Zulip Luke Boswell (Aug 24 2026 at 04:10):

I think my head just exploded with ideas ... I've been sitting on this general theme of a performance observatory and I think we just hit on a goldmine for how to actually do it properly.

view this post on Zulip Luke Boswell (Aug 24 2026 at 04:12):

Like is there any better binary encoding stable widely supported data format than sqlite?

view this post on Zulip Matthieu Pizenberg (Aug 24 2026 at 09:23):

@Luke Boswell sqlite-everything ^^ https://fzakaria.com/2026/08/23/your-executable-is-a-sqlite-database

view this post on Zulip Luke Boswell (Aug 25 2026 at 11:36):

Matthieu Pizenberg said:

Luke Boswell sqlite-everything ^^ https://fzakaria.com/2026/08/23/your-executable-is-a-sqlite-database

Circling back on this here is an idea using sqlite for roc-ray https://github.com/lukewilliamboswell/roc-ray/issues/178

view this post on Zulip Tobias Steckenborn (Aug 26 2026 at 14:52):

mhh what exactly does the "specializing" step survey, so in case it takes quite long, what's the likely root cause to investigate?

CleanShot 2026-08-26 at 16.52.15.png

view this post on Zulip Anton (Aug 26 2026 at 15:01):

In specialization generic code is transformed into specific faster version(s) based on known information like fixed arguments and known types.

view this post on Zulip Tobias Steckenborn (Aug 26 2026 at 15:02):

guess it running for 14 minutes would indicate something being off that I need to investigate :sweat_smile:

view this post on Zulip Anton (Aug 26 2026 at 15:02):

what's the likely root cause

A bunch of generic functions that get called from a bunch of different paths.

view this post on Zulip Anton (Aug 26 2026 at 15:03):

Are you using the release a compiler or a debug build?

view this post on Zulip Tobias Steckenborn (Aug 26 2026 at 15:03):

nightly-2026-08-13-2fdd90e

view this post on Zulip Anton (Aug 26 2026 at 15:03):

Feel free to toss the source code in an issue, we can minimize and investigate

view this post on Zulip Tobias Steckenborn (Aug 26 2026 at 15:04):

will first try to update and see if I can locate the issue

view this post on Zulip Anton (Aug 26 2026 at 15:04):

Yeah, we've landed a lot of fixes since 08-13

view this post on Zulip Richard Feldman (Aug 26 2026 at 18:36):

yeah 14 minutes is prob some pathological compiler thing that needs to be fixed, not a problem with your code :smile:

view this post on Zulip Aurélien Geron (Aug 26 2026 at 23:18):

It looks like roc test is significantly faster today than 3 days ago with both --opt=speed and --opt=dev:
image.png
image.png

view this post on Zulip Aurélien Geron (Aug 26 2026 at 23:19):

Side-note: please let me know if these plots are not useful, I don't want to spam everyone. :sweat_smile:

view this post on Zulip Luke Boswell (Aug 26 2026 at 23:25):

I'm loving the plots!

view this post on Zulip Luke Boswell (Aug 26 2026 at 23:31):

Curious that dev has a floor on it? oh that was the 24th version only and we fixed that?

view this post on Zulip Aurélien Geron (Aug 26 2026 at 23:35):

Thanks @Luke Boswell, I'll continue posting those then. :+1:
Yes, the 24th had an issue where the time was at least ~130ms. This has been fixed, apparently.

view this post on Zulip Luke Boswell (Aug 26 2026 at 23:37):

Yeah I saw that fix roll through https://github.com/roc-lang/roc/pull/10916

view this post on Zulip Richard Feldman (Aug 28 2026 at 01:20):

yeah I had something based on your previous plots

view this post on Zulip Richard Feldman (Aug 28 2026 at 01:20):

but I've been moving so I'm very disorganized right now :sweat_smile:

view this post on Zulip Richard Feldman (Aug 28 2026 at 01:20):

I'm not keeping track of what fixes are in what state haha

view this post on Zulip Niclas Ahden (Aug 28 2026 at 10:51):

I'm trying to migrate a large app and found this quadratic behaviour: https://github.com/roc-lang/roc/issues/10978

My server takes 1m 33s to build, so I've been troubleshooting on that. The client hasn't finished after 30 min, so I think there may be more issues lurking, which I'm trying to reduce now!

view this post on Zulip Niclas Ahden (Aug 28 2026 at 12:54):

Troubleshooting the client (wasm) build led me to this:

https://github.com/roc-lang/roc/issues/10979
https://github.com/roc-lang/roc/issues/10980

These two together seems to balloon the wasm size which makes LLVM take way too long (more than 30 min in my case). dev builds give me 100+ MB of wasm, so I technically can ship, but ... maybe, maybe :sweat_smile:

view this post on Zulip Niclas Ahden (Sep 02 2026 at 18:30):

phew! I've been pulling my hair trying to get this app to compile, but it's been hanging in compilation and/or OOM:ing, and the issues were difficult to minimally reproduce. I've finally narrowed down these two culprits :raised_hands:

https://github.com/roc-lang/roc/issues/11072
https://github.com/roc-lang/roc/issues/11073

There may be more hiding in there, but I'm throwing in the diagnostics towel at this point :sweat_smile:

view this post on Zulip Richard Feldman (Sep 02 2026 at 18:41):

wow, thank you for the repros - will be super helpful to fixing! :smiley:

view this post on Zulip Niclas Ahden (Sep 02 2026 at 18:46):

One for Roc and Roc for all! :D

view this post on Zulip Niclas Ahden (Sep 04 2026 at 08:27):

Thanks Richard for solving both the performance issues and the compilation bugs! I'm heading back out on my adventure! :)

view this post on Zulip Niclas Ahden (Sep 04 2026 at 15:26):

Fixing the issues above made a huge difference! The compilation times are way faster, from 16 min down to 82.5s, 7 min down to 37.9s, and the clients used to stall/OOM and now they're at 11-14 seconds!

Here are some new numbers:

┌─────────────────────────┬──────────────────┬───────────┬─────────────┬─────────────┐
│       entrypoint        │ roc check (cold) │ --opt=dev │ --opt=speed │ speed ÷ dev │
├─────────────────────────┼──────────────────┼───────────┼─────────────┼─────────────┤
│ server/main.roc         │ 0.75s            │ 82.5s     │ 249.5s      │ 3.0×        │
├─────────────────────────┼──────────────────┼───────────┼─────────────┼─────────────┤
│ jobs/main.roc           │ 0.34s            │ 37.9s     │ 197.9s      │ 5.2×        │
├─────────────────────────┼──────────────────┼───────────┼─────────────┼─────────────┤
│ client/Portal/main.roc  │ 0.28s            │ 11.7s     │ 135.8s      │ 11.6×       │
├─────────────────────────┼──────────────────┼───────────┼─────────────┼─────────────┤
│ client/Website/main.roc │ 0.44s            │ 13.3s     │ 184.2s      │ 13.9×       │
└─────────────────────────┴──────────────────┴───────────┴─────────────┴─────────────┘

Now that I can build the project I was able to identify and minimally reproduce two more perf issues:

https://github.com/roc-lang/roc/issues/11100
https://github.com/roc-lang/roc/issues/11103

This progress is so exciting! :smile:

view this post on Zulip Niclas Ahden (Sep 05 2026 at 10:55):

Thank you Richard! Fixing those gave another huge boost, making it between 1.18 and 3.9x faster! Here are the numbers:

┌─────────────────────────┬───────────┬─────────────────────┬───────────────────────┬─────────────┐
│       Entrypoint        │ roc check │      --opt=dev      │      --opt=speed      │ speed ÷ dev │
├─────────────────────────┼───────────┼─────────────────────┼───────────────────────┼─────────────┤
│ server/main.roc         │ 0.78s     │ 36.4s (2.3× faster) │ 202.0s (1.24× faster) │ 5.5×        │
├─────────────────────────┼───────────┼─────────────────────┼───────────────────────┼─────────────┤
│ jobs/main.roc           │ 0.32s     │ 9.6s  (3.9× faster) │ 167.7s (1.18× faster) │ 17.5×       │
├─────────────────────────┼───────────┼─────────────────────┼───────────────────────┼─────────────┤
│ client/Website/main.roc │ 0.43s     │ 12.9s (unchanged)   │ 182.9s (unchanged)    │ 14.1×       │
├─────────────────────────┼───────────┼─────────────────────┼───────────────────────┼─────────────┤
│ client/Portal/main.roc  │ 0.29s     │ 12.0s (unchanged)   │ 135.5s (unchanged)    │ 11.3×       │
└─────────────────────────┴───────────┴─────────────────────┴───────────────────────┴─────────────┘

To make it more interesting I thought we could start tracking "lines/s", so here's a breakdown of the project structure:

┌────────────────┬─────────┬─────────────┬─────────┬──────────┐
│   entrypoint   │ modules │ total lines │ in-repo │ external │
├────────────────┼─────────┼─────────────┼─────────┼──────────┤
│ server         │ 230     │ 55,123      │ 42,942  │ 12,181   │
├────────────────┼─────────┼─────────────┼─────────┼──────────┤
│ jobs           │ 143     │ 32,821      │ 20,464  │ 12,357   │
├────────────────┼─────────┼─────────────┼─────────┼──────────┤
│ client/Website │ 96      │ 23,196      │ 15,695  │ 7,501    │
├────────────────┼─────────┼─────────────┼─────────┼──────────┤
│ client/Portal  │ 56      │ 19,014      │ 11,513  │ 7,501    │
└────────────────┴─────────┴─────────────┴─────────┴──────────┘

Here's how Roc performed before fixing the issues above:

┌────────────────┬────────┬───────────────┬─────────────┐
│   entrypoint   │ lines  │      dev      │    speed    │
├────────────────┼────────┼───────────────┼─────────────┤
│ server         │ 55,123 │ 668 lines/s   │ 221 lines/s │
├────────────────┼────────┼───────────────┼─────────────┤
│ jobs           │ 32,821 │ 867 lines/s   │ 166 lines/s │
├────────────────┼────────┼───────────────┼─────────────┤
│ client/Website │ 23,196 │ 1,744 lines/s │ 126 lines/s │
├────────────────┼────────┼───────────────┼─────────────┤
│ client/Portal  │ 19,014 │ 1,627 lines/s │ 140 lines/s │
└────────────────┴────────┴───────────────┴─────────────┘

And here's a summary table of how it's doing now (same data as up top, but now with lines/s):

┌─────────────────────────┬────────┬───────────┬───────────────────────────────┬─────────────────────────────────┬─────────────┐
│       Entrypoint        │  LOC   │ roc check │              dev              │              speed              │ speed ÷ dev │
├─────────────────────────┼────────┼───────────┼───────┬─────────┬─────────────┼────────┬─────────┬──────────────┼─────────────┤
│                         │        │           │ time  │ lines/s │ improvement │  time  │ lines/s │ improvement  │             │
├─────────────────────────┼────────┼───────────┼───────┼─────────┼─────────────┼────────┼─────────┼──────────────┼─────────────┤
│     server/main.roc     │ 55,123 │   0.78s   │ 36.4s │  1,513  │ 2.3× faster │ 202.0s │   273   │ 1.24× faster │    5.5×     │
├─────────────────────────┼────────┼───────────┼───────┼─────────┼─────────────┼────────┼─────────┼──────────────┼─────────────┤
│      jobs/main.roc      │ 32,821 │   0.32s   │ 9.6s  │  3,422  │ 3.9× faster │ 167.7s │   196   │ 1.18× faster │    17.5×    │
├─────────────────────────┼────────┼───────────┼───────┼─────────┼─────────────┼────────┼─────────┼──────────────┼─────────────┤
│ client/Website/main.roc │ 23,196 │   0.43s   │ 12.9s │  1,792  │      ~      │ 182.9s │   127   │      ~       │    14.1×    │
├─────────────────────────┼────────┼───────────┼───────┼─────────┼─────────────┼────────┼─────────┼──────────────┼─────────────┤
│ client/Portal/main.roc  │ 19,014 │   0.29s   │ 12.0s │  1,581  │      ~      │ 135.5s │   140   │      ~       │    11.3×    │
└─────────────────────────┴────────┴───────────┴───────┴─────────┴─────────────┴────────┴─────────┴──────────────┴─────────────┘

Now that iteration time is faster it's easier to find more and more! I've been guiding a bunch of agents on this for the past five hours and this seems like a good place to stop. Hope this helps! :roc: :smiley:

https://github.com/roc-lang/roc/issues/11127
https://github.com/roc-lang/roc/issues/11128
https://github.com/roc-lang/roc/issues/11129
https://github.com/roc-lang/roc/issues/11130
https://github.com/roc-lang/roc/issues/11131
https://github.com/roc-lang/roc/issues/11132
https://github.com/roc-lang/roc/issues/11133
https://github.com/roc-lang/roc/issues/11134

view this post on Zulip Luke Boswell (Sep 05 2026 at 11:24):

I feel like count and running total for allocations could be good metric to track too

view this post on Zulip Luke Boswell (Sep 05 2026 at 11:26):

This kind of stats work is why I built the roc ray performance observatory which dumps basically every metric we can find into a sqlite db

https://github.com/lukewilliamboswell/roc-ray/blob/main/docs/observatory.md

I'm not sure if you could do the same for Joy -- but maybe it's possible to have a second host impl (so production builds aren't too large) that bundles sqlite and produces that in-memory?

view this post on Zulip Luke Boswell (Sep 05 2026 at 11:29):

Also I would say this is idea very experimental -- I think I'm the only person who has used it at all so far.

view this post on Zulip Niclas Ahden (Sep 05 2026 at 11:40):

That looks cool! Right now I'm just focused on getting the general low-hanging fruit chopped down, and then I can get into more Joy-specific instrumentation later :)

view this post on Zulip Niclas Ahden (Sep 05 2026 at 17:40):

Two more:
https://github.com/roc-lang/roc/issues/11143
https://github.com/roc-lang/roc/issues/11144

I bet my favorite pair of gloves that solving the issues reported hitherto will bring about 1-second compile times!

view this post on Zulip Aurélien Geron (Sep 07 2026 at 22:38):

Comparing August 27 vs September 7 speed with roc test --opt=dev:

image.png

Looks the same (or very slightly worse) for <50ms exercises, slightly better for 50ms to 1s exercises, and much better for the four exercises that used to take 4 to 10 seconds, and which now take 2-3 seconds.

view this post on Zulip Aurélien Geron (Sep 07 2026 at 22:40):

There's no obvious change when comparing the same dates with roc test --opt=speed:

image.png

view this post on Zulip Richard Feldman (Sep 07 2026 at 23:07):

yeah --opt=speed isn't something I'm planning to try and improve until like 2027 :sweat_smile:

view this post on Zulip Richard Feldman (Sep 07 2026 at 23:08):

other than trying to keep it in the range of "doesn't take a gazillion years"

view this post on Zulip Richard Feldman (Sep 07 2026 at 23:09):

because llvm is so slow that basically nothing else will be noticeable until we are doing so many of our optimizations that we can drop llvm as a dependency, but that's a very big project

view this post on Zulip Lukas Juhrich (Sep 08 2026 at 12:12):

Richard Feldman said:

drop llvm as a dependency

I would not have guessed this was a goal. That sounds extremely ambitious.
Does that mean we'll eventually get an „advent of roc compiler optimizations“ series in the spirit of what Matt Godbolt did? :D

view this post on Zulip Richard Feldman (Sep 08 2026 at 13:48):

no concrete plans...I just have a general sense based on how optimizations have gone so far that at some point it will make sense

view this post on Zulip Richard Feldman (Sep 08 2026 at 13:50):

we already know how to emit machine instructions for all the targets we support (because of dev builds), and several Roc-specific optimizations already overlap with what LLVM does (because LLVM's version can't take into account information Roc's compiler has access to), and I think that's going to increase...at some point it becomes reasonable to look at "if we closed the gap, what would that do to our optimized build speed and binary size?

view this post on Zulip Richard Feldman (Sep 08 2026 at 13:50):

and I suspect it will turn out to make sense overall. But I could be wrong!

view this post on Zulip Niclas Ahden (Sep 12 2026 at 08:06):

Richard is a beast! All of the issues above have been solved and it's now between 1.4x to 3.2x faster, again!

┌─────────────────────────┬────────┬───────────┬───────────────────────────────┬──────────────────────────────────┬─────────────┐
│       Entrypoint        │  LOC   │ roc check │              dev              │              speed               │ speed ÷ dev │
├─────────────────────────┼────────┼───────────┼───────┬─────────┬─────────────┼────────┬─────────┬───────────────┼─────────────┤
│                         │        │           │ time  │ lines/s │ improvement │  time  │ lines/s │  improvement  │             │
├─────────────────────────┼────────┼───────────┼───────┼─────────┼─────────────┼────────┼─────────┼───────────────┼─────────────┤
│     server/main.roc     │ 57,901 │   0.16s   │ 16.9s │  3,421  │ 2.2× faster │ 141.4s │   410   │  1.4× faster  │    8.4×     │
├─────────────────────────┼────────┼───────────┼───────┼─────────┼─────────────┼────────┼─────────┼───────────────┼─────────────┤
│      jobs/main.roc      │ 33,670 │   0.10s   │ 7.1s  │  4,768  │ 1.4× faster │ 75.4s  │   446   │  2.2× faster  │    10.7×    │
├─────────────────────────┼────────┼───────────┼───────┼─────────┼─────────────┼────────┼─────────┼───────────────┼─────────────┤
│ client/Website/main.roc │ 23,382 │   0.09s   │ 7.1s  │  3,275  │ 1.8× faster │ 70.5s  │   332   │  2.6× faster  │    9.9×     │
├─────────────────────────┼────────┼───────────┼───────┼─────────┼─────────────┼────────┼─────────┼───────────────┼─────────────┤
│ client/Portal/main.roc  │ 19,515 │   0.06s   │ 6.7s  │  2,926  │ 1.8× faster │ 42.3s  │   462   │  3.2× faster  │    6.3×     │
└─────────────────────────┴────────┴───────────┴───────┴─────────┴─────────────┴────────┴─────────┴───────────────┴─────────────┘

I must apologize, however. I aimed to produce enough issues to bring about 1-second compile times, but it seems I failed. My gloves are available for pickup in Stockholm, Sweden, at Odenplan's metro station. I'm a man of my word :smile:

Here's some more potential:
https://github.com/roc-lang/roc/issues/11321
https://github.com/roc-lang/roc/issues/11322
https://github.com/roc-lang/roc/issues/11323
https://github.com/roc-lang/roc/issues/11324
https://github.com/roc-lang/roc/issues/11325
https://github.com/roc-lang/roc/issues/11326
https://github.com/roc-lang/roc/issues/11327

view this post on Zulip Luke Boswell (Sep 12 2026 at 09:21):

Cool, server.main looks like it's gone from 16 min down to 82.5s down to 16.9s now :grinning_face_with_smiling_eyes:

view this post on Zulip Niclas Ahden (Sep 12 2026 at 10:06):

Indeed, it’s a tremendous improvement! And the clients went from hanging/OOM:ing to success in ~7s :partying_face:

view this post on Zulip Richard Feldman (Sep 12 2026 at 11:41):

love seeing the progress, thanks for measuring and reporting all these @Niclas Ahden! :smiley:

view this post on Zulip Richard Feldman (Sep 12 2026 at 11:42):

out of curiosity, are these all --no-cache builds? And are the lines/s measurements including dependencies (e.g. the platform and any app or package imports) or just the lines in the entrypoint file itself?

view this post on Zulip Luke Boswell (Sep 13 2026 at 10:57):

Hey this is cool https://github.com/roc-lang/roc/pull/11368

Screenshot 2026-09-13 at 20.57.34.png

view this post on Zulip Niclas Ahden (Sep 13 2026 at 17:19):

Richard Feldman said:

out of curiosity, are these all --no-cache builds?

They're not using --no-cache, but here's what that looks like:

┌─────────────────────────────┬──────────┬──────────┬─────────┬──────────────┐
│           Target            │ no-cache │  cached  │  saved  │ cached speed │
├─────────────────────────────┼──────────┼──────────┼─────────┼──────────────┤
│ check  server               │   0.66s  │   0.14s  │  0.52s  │  4.7× faster │
│ check  jobs                 │   0.37s  │   0.09s  │  0.28s  │  4.1× faster │
│ check  client/Website       │   0.31s  │   0.08s  │  0.23s  │  3.9× faster │
│ check  client/Portal        │   0.25s  │   0.05s  │  0.20s  │  5.0× faster │
├─────────────────────────────┼──────────┼──────────┼─────────┼──────────────┤
│ build  server         dev   │  18.20s  │  17.61s  │  0.59s  │     3.3%     │
│ build  jobs           dev   │   7.64s  │   7.41s  │  0.23s  │     3.0%     │
│ build  client/Website dev   │   7.63s  │   7.40s  │  0.23s  │     3.0%     │
│ build  client/Portal  dev   │   7.11s  │   6.92s  │  0.19s  │     2.7%     │
├─────────────────────────────┼──────────┼──────────┼─────────┼──────────────┤
│ build  server         speed │ 152.75s  │ 152.71s  │  0.04s  │     0.0%     │
│ build  jobs           speed │  81.70s  │  81.27s  │  0.43s  │     0.5%     │
│ build  client/Website speed │  77.14s  │  77.01s  │  0.13s  │     0.2%     │
│ build  client/Portal  speed │  45.93s  │  45.71s  │  0.22s  │     0.5%     │
└─────────────────────────────┴──────────┴──────────┴─────────┴──────────────┘

Surprisingly small difference :thinking: Could this be right?

Richard Feldman said:

And are the lines/s measurements including dependencies (e.g. the platform and any app or package imports) or just the lines in the entrypoint file itself?

Yes, they include everything: app code, deps, and the Roc part of the platform. In the table below you see "in-repo" which is app code, and "external" is deps+platform:

┌────────────────┬─────────┬─────────────┬─────────┬──────────┐
│   entrypoint   │ modules │ total lines │ in-repo │ external │
├────────────────┼─────────┼─────────────┼─────────┼──────────┤
│ server         │ 230     │ 55,123      │ 42,942  │ 12,181   │
├────────────────┼─────────┼─────────────┼─────────┼──────────┤
│ jobs           │ 143     │ 32,821      │ 20,464  │ 12,357   │
├────────────────┼─────────┼─────────────┼─────────┼──────────┤
│ client/Website │ 96      │ 23,196      │ 15,695  │ 7,501    │
├────────────────┼─────────┼─────────────┼─────────┼──────────┤
│ client/Portal  │ 56      │ 19,014      │ 11,513  │ 7,501    │
└────────────────┴─────────┴─────────────┴─────────┴──────────┘

view this post on Zulip Richard Feldman (Sep 13 2026 at 18:57):

it could be right, especially if we're invalidating too much cache...which file(s) are being the changed during the cached builds?

view this post on Zulip Richard Feldman (Sep 13 2026 at 19:01):

I'd also love to see --timings on those dev ones if you have the chance, to see where all the time is going after type-checking :smile:

view this post on Zulip Richard Feldman (Sep 13 2026 at 19:08):

oh also, we are currently only caching up through type checking - so actually those cache numbers make sense: big percentage improvement on type-checking, but since type-checking is a small percentage of total build time, it has a small impact overall

view this post on Zulip Richard Feldman (Sep 13 2026 at 19:09):

I have a design for caching later steps of compilation but the implementation will take awhile to land

view this post on Zulip Aurélien Geron (Sep 14 2026 at 04:18):

Just thought I'd compare the roc test time using the latest nightly (2026-09-12) versus the first one I recorded back on August 8:

image.png

Virtually all exercises that used to take more than 100ms run much faster today.

view this post on Zulip Luke Boswell (Sep 20 2026 at 09:56):

package-stress.roc

https://gist.github.com/lukewilliamboswell/eea43a8c3e057a3c1da5c0b9e0312d76

cold build - 49.3 seconds

~/roc_nightly-macos_apple_silicon-2026-09-18-1d982dc/roc build --no-cache --timings examples/package-stress.roc

warm build - 47.7 seconds

~/Documents/GitHub/roc main $ ~/roc_nightly-macos_apple_silicon-2026-09-18-1d982dc/roc build --timings examples/package-stress.roc

cold dev build - 5.6 seconds

~/roc_nightly-macos_apple_silicon-2026-09-18-1d982dc/roc build --opt=dev --timings --no-cache examples/package-stress.roc

warm dev build - 0.6 seconds :tada:

view this post on Zulip Luke Boswell (Sep 20 2026 at 10:08):

Maybe we need to do more with these packages to stress it harder ... :shrug:

view this post on Zulip Richard Feldman (Sep 20 2026 at 12:43):

the last one is encouraging :smiley:

view this post on Zulip Richard Feldman (Sep 20 2026 at 12:44):

what happens if you modify the app file and rebuild? Still sub-second?


Last updated: Sep 24 2026 at 15:59 UTC