Joovy - Faster compilation

Hey,

Paul here, the guy behind Flexible Julia. So there’s been a couple of posts regarding Julia performance that have been bugging me (in particular this one: julia-debugging-is-extremely-slow) by @tue. So i started to mess with different ideas on how to improve it further. And being a Java guy, I thought, maybe we just miss something like Groovy for Java (only for Julia), ie. a compiler that optimizes when something is being compiled.


What’s Joovy.jl:
I built a compilation layer that makes Julia feel faster during development by not compiling everything at full optimization upfront. It is called Joovy and you can find it here: github.com/ilscipio/joovy


Explainer:
Julia’s compiler is thorough. Every function you touch gets fully optimized before you can use it. That is great for production code but painful during development. Precompilation is also incredibly slow, since you compile all dependencies in full. Regardless of what is needed to execute.

So Joovy is like an addon to the compiler. Instead of compiling everything at full optimization, Joovy uses three tiers. Tier 0 is basically not-compiled. Fast to load, but slow to execute. Tier 2 is native Julia. Tier 1 is the middle ground. It does lazy module loading. When you open a file, Joovy parses it and builds a dependency graph but compiles nothing. When you actually call a function, it compiles that function and its dependencies. Everything else stays untouched. External packages get the same treatment through configurable dev-mode tiering. Functions start at tier 1. If you call them enough, they get promoted to native speed (tier 2) in the background. You never wait for the full compile on first use.

So this is not Revise.jl or Julia compiler, it sits in between as a way to optimize how something is processed. (Revise compiles and hot-swaps on existing code, native compiler handles the full packages, Joovy optimizes when compilation happens).


Experimental

This is all experimental at this point. I built it primarily for Flexible Julia so the IDE can handle compilation more intelligently behind the scenes. And you can turn it on there in the settings (requires a repl restart). But the package works standalone too. Since this is all new, it is of course possible I messed up. Maybe my own experiment result are misleading, maybe it is not working everywhere. Who knows - but this should improve over time.

If you are curious, check it out: GitHub - ilscipio/joovy: Dynamic compilation engine for Julia. Tiered optimization, lazy modules, and hot-swapping at runtime. · GitHub

Feedback and bugfixes welcome. If anyone has thoughts on the approach or wants to poke holes in the design, I am all ears. Obviously, this is experimental for a reason at this point…

Oh and: this is open source. So anyone who wants to contribute is well invited to do so. Fork, expand, create PRs or do whatever.

That’s… amazing? What’s the catch?

I don’t want to sound too negative, the question is motivated by my not having enough of a technical understanding to get how this works, and the fact that something like this has been discussed in the community for as long as I can remember (and I stayed using Julia in 0.3 days!), so the fact that it hadn’t happened let me to believe that it was a herculean task requiring the concerted long term efforts of many of the core devs.

Is this something that everyone should be using all the time or are there drawbacks to the approach that make it unsuitable for some situations

It is definitely not something you should be using “all the time”. It is something you should be using during development and very much experimental.

Since you asked for it, here’s the caveat: it is “good enough” to use when you are developing, because waiting for something to process while you are editing is probably better than living with a long compilation process. (I really did have Groovy in mind with this) But during production use, the native compiler is probably better because things are always fast at startup. (and you only deploy once).

It is also “not great” when you use it without the help of an ide that can auto wrap calls and handle the syntax for you. It is also only a first shot, my own experiments were limited to my own code. So expact the code to be unoptimized yet. We can surely do better over time.

A comparison:

joovy:


[ Info: FlexibleIPC: Trying 1 host(s) on port 52342: 127.0.0.1
[ Info: FlexibleIPC: Connected to IDE on 127.0.0.1:52342
[ Flexible Julia IDE integration active ]

┌ Plugin-injected modules in Main:
│   FlexibleIPC
│   FlexibleJuliaDisplay
│   VSCodeServer
├ Plugin-set environment variables:
│   GKSwstype = 100
│   MPLBACKEND = Agg
│   JULIA_IDE_DISPLAY = 1
│   GMT_SESSION_TYPE = extern
│   DISPLAY_IN_VSC = true
│   JULIA_IDE_AUTO_JOOVY = 1
│   JULIA_IDE_SVG_PLOTS = 1
│   JULIA_IDE_SHOW_INJECTIONS = 1
├ Display stack:
│   [1] TextDisplay
│   [2] Main.FlexibleJuliaDisplay.IDEDisplay
└ Hook version: 2026.9.5

Precompiling Joovy finished.
  1 dependency successfully precompiled in 2 seconds
[ Info: Joovy loaded - dev mode active (tier 1)
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.12.3 (2025-12-15)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org release
|__/                   |

julia> println("# Executing 149 lines: # Joovy Compilation Benchmark # # Open this file in the IDE,..."); include("C:/Users/pp/AppData/Local/Temp/julia_repl_11564966733672911642.jl")
# Executing 149 lines: # Joovy Compilation Benchmark # # Open this file in the IDE,...

======================================================================
  JOOVY COMPILATION BENCHMARK
  Joovy detected: YES
======================================================================

──────────────────────────────────────────────────────────────────────
  PASS 1 — First call (includes compilation)
──────────────────────────────────────────────────────────────────────
  Running: first call
    make_scatter            1.831 s
    make_heatmap            0.175 s
    make_histogram          0.258 s
    make_dataframe          0.046 s
    make_surface            0.085 s
    make_contour            0.147 s
    make_bar_chart          0.203 s
    make_line_plot          0.158 s
    full_report             0.311 s
    heavy_report            0.478 s
    TOTAL                   3.690 s

──────────────────────────────────────────────────────────────────────
  PASS 2 — Second call (already compiled)
──────────────────────────────────────────────────────────────────────
  Running: second call
    make_scatter            0.000 s
    make_heatmap            0.000 s
    make_histogram          0.001 s
    make_dataframe          0.000 s
    make_surface            0.000 s
    make_contour            0.000 s
    make_bar_chart          0.001 s
    make_line_plot          0.000 s
    full_report             0.002 s
    heavy_report            0.004 s
    TOTAL                   0.010 s

======================================================================
  SUMMARY
======================================================================
  Function                1st (s)    2nd (s)    Speedup
  ------------------------------------------------------
  make_scatter              1.831      0.000    3665.6x
  make_heatmap              0.175      0.000     466.0x
  make_histogram            0.258      0.001     299.2x
  make_dataframe            0.046      0.000    1704.3x
  make_surface              0.085      0.000     273.5x
  make_contour              0.147      0.000     531.5x
  make_bar_chart            0.203      0.001     361.6x
  make_line_plot            0.158      0.000     439.0x
  full_report               0.311      0.002     132.9x
  heavy_report              0.478      0.004     115.1x
  ------------------------------------------------------
  TOTAL                     3.690      0.010     378.0x

  Mode: JOOVY (lazy tier-1 compile on first call)
  Tip:  Run once with Joovy ON, restart REPL with Joovy OFF, run again.
        Compare the 1st-call totals to see lazy vs eager compile cost.
======================================================================

(first_call = [1.83061, 0.174924, 0.257977, 0.045505, 0.0850444, 0.1467, 0.202772, 0.157716, 0.310984, 0.477975], second_call = [0.0004994, 0.0003754, 0.0008621, 2.67e-5, 0.0003109, 0.000276, 0.0005608, 0.0003593, 0.0023396, 0.0041526], names = ["m
ake_scatter", "make_heatmap", "make_histogram", "make_dataframe", "make_surface", "make_contour", "make_bar_chart", "make_line_plot", "full_report", "heavy_report"], total_1st = 3.69021, total_2nd = 0.0097628, joovy = true)

julia>

Native:

[ Info: FlexibleIPC: Trying 1 host(s) on port 56168: 127.0.0.1
[ Info: FlexibleIPC: Connected to IDE on 127.0.0.1:56168
[ Flexible Julia IDE integration active ]

┌ Plugin-injected modules in Main:
│   FlexibleIPC
│   FlexibleJuliaDisplay
│   VSCodeServer
├ Plugin-set environment variables:
│   GKSwstype = 100
│   MPLBACKEND = Agg
│   JULIA_IDE_DISPLAY = 1
│   GMT_SESSION_TYPE = extern
│   DISPLAY_IN_VSC = true
│   JULIA_IDE_SVG_PLOTS = 1
│   JULIA_IDE_SHOW_INJECTIONS = 1
├ Display stack:
│   [1] TextDisplay
│   [2] Main.FlexibleJuliaDisplay.IDEDisplay
└ Hook version: 2026.9.5

               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.12.3 (2025-12-15)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org release
|__/                   |

julia> println("# Executing 149 lines: # Joovy Compilation Benchmark # # Open this file in the IDE,..."); include("C:/Users/pp/AppData/Local/Temp/julia_repl_16242062654936921354.jl")
# Executing 149 lines: # Joovy Compilation Benchmark # # Open this file in the IDE,...
Precompiling Plots finished.
  7 dependencies successfully precompiled in 96 seconds. 172 already precompiled.
Precompiling DataFrames finished.
  1 dependency successfully precompiled in 60 seconds

======================================================================
  JOOVY COMPILATION BENCHMARK
  Joovy detected: NO
======================================================================

──────────────────────────────────────────────────────────────────────
  PASS 1 — First call (includes compilation)
──────────────────────────────────────────────────────────────────────
  Running: first call
    make_scatter            2.055 s
    make_heatmap            0.117 s
    make_histogram          0.253 s
    make_dataframe          0.042 s
    make_surface            0.080 s
    make_contour            0.136 s
    make_bar_chart          0.209 s
    make_line_plot          0.131 s
    full_report             0.313 s
    heavy_report            0.188 s
    TOTAL                   3.524 s

──────────────────────────────────────────────────────────────────────
  PASS 2 — Second call (already compiled)
──────────────────────────────────────────────────────────────────────
  Running: second call
    make_scatter            0.000 s
    make_heatmap            0.001 s
    make_histogram          0.001 s
    make_dataframe          0.000 s
    make_surface            0.000 s
    make_contour            0.000 s
    make_bar_chart          0.001 s
    make_line_plot          0.001 s
    full_report             0.002 s
    heavy_report            0.004 s
    TOTAL                   0.010 s

======================================================================
  SUMMARY
======================================================================
  Function                1st (s)    2nd (s)    Speedup
  ------------------------------------------------------
  make_scatter              2.055      0.000    4761.6x
  make_heatmap              0.117      0.001     209.7x
  make_histogram            0.253      0.001     246.9x
  make_dataframe            0.042      0.000    1410.6x
  make_surface              0.080      0.000     169.9x
  make_contour              0.136      0.000     326.6x
  make_bar_chart            0.209      0.001     370.4x
  make_line_plot            0.131      0.001     251.6x
  full_report               0.313      0.002     145.7x
  heavy_report              0.188      0.004      48.5x
  ------------------------------------------------------
  TOTAL                     3.524      0.010     351.1x

  Mode: STANDARD (eager full compile on include)
  Tip:  Run once with Joovy ON, restart REPL with Joovy OFF, run again.
        Compare the 1st-call totals to see lazy vs eager compile cost.
======================================================================

(first_call = [2.05464, 0.117376, 0.252827, 0.0416138, 0.0801208, 0.135577, 0.209271, 0.131185, 0.313229, 0.187727], second_call = [0.0004315, 0.0005597, 0.0010239, 2.95e-5, 0.0004716, 0.0004151, 0.000565, 0.0005215, 0.0021502, 0.0038681], names =
["make_scatter", "make_heatmap", "make_histogram", "make_dataframe", "make_surface", "make_contour", "make_bar_chart", "make_line_plot", "full_report", "heavy_report"], total_1st = 3.52357, total_2nd = 0.0100361, joovy = false)

Note: precompilation time is almost gone at the cost of a slightly slower execution time. I need to check if this was still related to my joovy caches, so please feel free to run your own tests.

Nice work! This sounds similar to this attempt in the Julia repo: [experimental] codegen: add tiered compilation - Pull Request #61888 - JuliaLang/julia - GitHub. I’m not sure if the implementation is, but reading the comments in that PR results don’t seem currently very promising, but there is still activity so still to see I think. Is the approach the same as Joovy there? I expect that something like this is very tied to the Julia compiler, and would benefit from an implementation in the core repo

Oh wow. I did not know about that at all. I skipped over it just now (only the first post) and looks very similar indeed from the basic concept. I guess if it started from a similar idea as mine, then ending up with a tiered approach feels natural. So not surprised. But that thread is interesting and I should check it out later!

Thanks for this!