Joovy - Faster compilation

This is really great to see - I have been bitten a number of times by seemingly random recompilations of projects when I start a new REPL, which is particularly painful when the project includes Makie, so being able to mitigate this during development is exciting to say the least. I primarily use neovim for my coding environment, so I appreciate that (certainly in the initial implementation) this package is not optimized for my setup. However, I wonder if it would be simple enough to provide some sort of interface via Preferences.jl, where the user could define in the LocalPreferences.toml file which compilation tier to use by default, and then be able to assign different external packages/internal modules to use a different compilation tier? In a similar vein, I suppose you could specify the internal functions to different tiers using something like


[Joovy]
default = tier_0
ModuleA = tier_1
ModuleA.some_function = tier_2

I appreciate that this might not be possible and that I may be misunderstanding something fundamental about Joovy from my quick skim of the repo, but thought I’d type this up in case it’s in any way useful as a suggestion.

Hey, thats actually a great idea. Let me think about it a bit, but I don’t see why not. I mean, right now everything is flagged by annotations, but we could also keep the code lean by a config like that.

I added a first version of this and pushed it to github last night. It ran fine on my tests today, but it would be great if you could try it yourself and give me some feedback :slight_smile:

Thanks for the suggestion, btw.

That’s very efficient - thank you! I’m about to leave for a vacation so probably won’t be able to test it out for a week, but I have a work project that I suspect this would be a good test case for so I’ll be sure to try it out ASAP and get back to you!

Incredible! Now what should I do with all the hours this saves…

@madppiper very interesting, congratulations! I am not an expert but is your design similar to JavaScriptCore - WebKit Documentation? Maybe it can be further inspiration, I think this was discussed somewhere in this forum as a way to improve the UX in Julia.

Thanks!

And thanks for the reference, I really need to read up on what they do. But in short: right now Joovy runs everything cheap first, then optimizes the hot functions in the background based on call counts. Julia already has a solid optimizer, so it’s really just about when you pay for it.

Right now I’m mostly experimenting, hoping it slowly turns into a much better experience in our tooling. It’s not trying to make Julia something it isn’t though.

Always happy for input! This is great.

I hope everyone is enjoying their summer-break? Anyway, I had some time to play around a bit more, so I just pushed an update.

Anyway, i had a second look at how reloads are handled. And turns out, I had left some room for improvement: if you reload a file, every definition in it got re-evaluated, even the ones you never touched. Julia then treats all of those as freshly redefined and invalidates their callers, so one small edit could cause recompiles all over the place. So I am now adding a cache layer. Joovy now hashes each definition and only re-evaluates what actually changed.

The second thing is a new idea. Joovy already knows the call graph of a lazily-loaded file, so instead of waiting for you to call a function and stall while it compiles, there’s now a small background queue that compiles the likely-next functions during idle time - one at a time, yielding in between, so the REPL never blocks on it. To be clear about the limits: Julia still generates native code the moment a concrete call happens, so this doesn’t make compilation free, it just moves it into time you weren’t using anyway. It’s off by default while I collect experience with it, but you can turn it on by setting “speculate = true” in the [Joovy] section of your LocalPreferences.toml if you want to try it.

How do you predict that?

Oh, there is a call-graph that I rely on. There is no “prediction” in that sense, but the call-graph connects changes in one function to the next. When you touch or promote a function, I queue what it calls plus the rest of that file, ranked by how many callers each has.

i myself encountered a similar problem when working on a big private Julia project, the development cycle was just too slow, but my solution was to replace Pkg.jl with my own Package manager, i think i should have read this post before i wrote tons of zig code to replace Pkg :sweat_smile:

You could try adding Joovy to JulIDE and experiment with it. Joovy is open source and I bet you can do similar things as I did with Flexible Julia and Joovy and test if it makes a difference in your work

thats actually a good idea! ill test it out :slight_smile: