JIT issues relevant to realtime applications

First off, Julia’s performance (once JIT compiled) is insane! How?! (rhetorical). In my gaming development environment my naïve Julia code beats my naïve C++ code (clang O2 Release version).

JIT is super useful for development, but once an app is running, there is no need to interact with any Julia scripts (ie, write or modify existing ones) - they would just run in a predetermined sort of way.

JIT compiling time can add up. If a realtime application level has 1000 scripts (not unheard of) and each takes just half a second to compile on average, the user would have to wait around for 8 minutes for the level to load which is unacceptable.

Solution: Package all level scripts together into one using the PackageCompiler? Any idea what the savings would be? Having one sys package per level an ok thing? Any issues I’m not thinking of?

As a side-note, some systems such as Apple OS’s categorically don’t allow JIT. Are there any future roadmap plans for AOT compiling, or is it out of the question?

7 Likes

Silly reply from me - how can an OS stop JIT?
Am I talking nonsense but surely Java is JIT? (that may be a huge misunderstanding on my part)

1 Like

The only thing I can think of is to mark pages as not executable and then kill the process if it begins executing pages that weren’t part of the program initially.

It looks like JIT is allowed with an explicit permission Allow Execution of JIT-compiled Code Entitlement | Apple Developer Documentation

A few years ago, there were two MIT PhD‘s working on robots (I don’t know their names by heart). That was also time critical. They managed to do it by avoiding allocations because garbage collection is also gonna be a problem otherwise.

But, regarding game development in general: why not Rust?

3 Likes

@rdeits :point_up:

4 Likes

I have no idea if Julia is a good language for game development. But probaly this estimate is not adequate. If you keep the Julia session alive during the execution, only the functions that where never compiled will be compiled again. Thus, for every script to take 0.5s to compile it should be a situation in which every script defines a whole new set of methods that are never defined before, which call inner functions that were also never called before, etc, so that the compile time accumulates like that. In a more “normal” scenario probably the scripts share a lot of methods and compilation will only be triggered for the new methods that each script defines.

Many people report good experiences with PackageCompiler, and I think that having the possibility of getting standalone binaries easily is definitely in the radar, but it is a challenging thing because of how Julia is structured. It is on the “still to do list” of the last “State of Julia” talk: https://youtu.be/IlFVwabDh6Q?t=535

3 Likes

This may not be as relevant for game dev, but have you heard of our (jokingly) Lord and Savior, LoopVectorization.jl? (This will trade shorter runtime performance for longer compile time though.)

Compile time depends on the code in question of course, but keep in mind that only the first call of a function has to compile (provided it’s a type stable function and follows the performance tips).

You can find the most up to date future plans in this talk, from this years’ juliacon:

The short version is, static binaries are very much planned (at time of writing, there’s even an open position for a compiler engineer at JuliaComputing). This may be non-trivial due to the dynamic nature of julia though.

At the moment, yes, PackageCompiler.jl is your best bet.


All in all, while I don’t think it’s impossible to use julia as a scripting language in a game, I’m not sure what this would look like for a player - the latency for the first compilation is real and some syntax errors/other errors are hard to debug for the lay person. Your mileage may vary.

7 Likes

You probably want to follow the development in:

https://github.com/JuliaLang/julia/pull/41936

9 Likes

Java is JIT, and Java doesn’t support AOT (yet, though there are lots of work on it, but not quite mature). Actually Java has tiered compiler, so compiler will generate bytecode at compile time. For those “cold” codes (execute only several times), it will just invoke interpreter over bytecodes at runtime. For the hot codes, JVM will optimize the bytecodes by reconstructing CFG and performing regular compiler optimization with runtime information, and then emit machine code. This is a rough picture, but this shows that Java is actually JIT.

5 Likes

Hey,

It’s possible we can even do better than go etc and have no runtime at all for a restricted class of code. Check out this doc by @jpsamaroo Static compilation in Julia - Google Docs if you want to get a sense of the direction/ where you can help out

2 Likes

Tbh I can’t remember if they have any automatic detection of JIT software but it violates Apple’s terms when uploading software to their stores.

The core engine code is written in C++ so Julia is being looked at as a scripting language solution for designers primarily. For an end user (designer, artist, etc), Rust is no upgrade from C++. Something dynamic that you don’t have to explicitly compile and is loosely typed is much better.
GC is a problem but for designer-centric scripting, it’s hard to get around. As mentioned before, lowering the expertise required is important. Some scripting environments do a good enough job, like in Unreal’s blueprints. Some are not - in Unity, c# devs often have to create their own pools of objects to draw from and manage in real-time. Julia’s approach seems good enough from my preliminary findings.
There are other options for game scripting such as Lua, but the performance tradeoff can be immense. Python is sometimes used but the GC is horrendous in it and in general, it’s pretty slow. Hashlink is decent, a bit less beginner friendly than other options, a bit less performant than others.
All in all, if the PackageCompiler solves the loading issue, I’d rather use Julia because it’s super fast, dynamic, decent GC, and loosely typed – unless I’m missing something here.

8 Likes

As an aside, there’s work on this from both ends, extracting static information to make compiled code, but also interpretation/tiered compilation.

Could you elaborate on this a bit? I’m trying to gather all the pro’s and con’s and don’t want to miss anything important. Are some of the error messages not clear?

Don’t get me wrong, it’s not that they’re impossible to debug, it’s just that I see some questions on here and on the issue tracker about error messages that stem from a wrong understanding of how the language works. For example, there was an issue a few weeks ago about a MethodError being thrown when trying to assert a return type of a method, where the last statement of the method returned an integer. In that case, you had to know that the return value of the last executed expression in a function will also be implicitly returned from that function and that an “assertion” of a return type just tries to convert that last value to the given return type (which resulted in a MethodError, as convert(Nothing, ::Int) is not defined). The user was confused because they didn’t know about the implicit return and thought not writing a literal return anywhere means nothing would be returned, as is the case in other languages. It’s these sorts of misunderstandings and wrong assumptions that I meant when I said that it’s sometimes hard to debug for the lay person that’s not already familiar with how julia works. Having someone with extensive julia experience on your team for these sorts of problems is probably a good idea.

As with any programming language, users have to learn how it works to some degree to be able to debug it themselves (which probably doesn’t get easier, as e.g. Debugger.jl is very much focused on a REPL workflow and I’m not sure how debugging with VSCode in an embedded setting would work - certainly an interesting avenue for new development though!).

I don’t think this is unsolvable, but it will probably require some dev/time investment to figure out how to make it ergonomic and helpful for your designers. (on that note, if you can integrate Revise.jl into your workflow, your designers will probably be very happy about not having to rebuild/restart from scratch :wink:)

3 Likes

I should explain that I delved very deeply into Java runtime behaviour when I worked in CFD in Formula1 that was on Itanium systems (really).

Surely Apple do not ban Java though? I am just asking out of curiosity - maybe Java is dead as a dodo these days.

1 Like

I’m mostly referring to iOS, not macOS

GameZero.jl is for “simple games”. I seem to remember it being quote “excellent” for it. By simple, they mean 2D games only I think, but while very rare I’ve seen this one 3D game (or actually a demo) written in Julia (probably with Vulkan.jl not that package), it’s one Youtube somewhere. There’s also shorter 7 min “No-overhead Game Development in Julia” JuliaCon2020 talk on the package (that mentions Breakout game in 140 lines of Julia code):

[There’s also Chess.jl, and AlphaZero.jl, so games like Go, are might be possible.]

My reading of the page, is you just need to enable it (not get Apple’s permission), on macOS. Maybe it’s the same now on iOS, but you can’t use Julia there anyway so I didn’t check. I believe at least historically it was banned there.

2 Likes

Julia should be worse than Java, and given that there’s not so much games written in Java (Minecraft is is an exception, and it’s rewritten in C++ recently by Microsoft for its bad performance), I don’t think Julia is appropriate for game developing. Julia’s JIT doesn’t have much use in game development, since most games have almost no need for runtime code generation, either they can be decided at compile time or use an embedded interpreter like Lua for scripting. C#/Java have reflection, a restricted form of codegen, but people use it carefully for performance consideration. Besides, Java/C#/C++ are static typed (so they have interface, type checking and so on), and they are more appropriate for this type of work.

If someone wants to develop some kinds of “scientific game” (for example, solving a lots of different types of differential equations at runtime) and have need for runtime code generation, then Julia will be a good fit. But I doubt whether these games have large market. A boardgame platform with AI and configurable script and mod system may be the fit for Julia, since it’s not interactive, compute-intensive and needs codegen…

1 Like

I’m not sure about that, and Java is a low bar… and you can precompile Julia code (and Julia without runtime code generation, i.e. without LLVM, is coming). Yes, Java has a very popular game, Minecraft, and Julia only PiCraft.jl, to interact with it, but something like Minecraft, could be done in Julia, and be better, and likely easier to develop from scratch that it was in Java. Or a better (looking) 3D game. Still, Julia doesn’t have a killer advantage for 3D game making, but neither a killer disadvantage over C# (usually used with a C++ game engine, which Julia could do too), which is very popular for games. Java does have a real-time garbage collector, as a non-default option, still people prefer Julia for hard-real-time robotics to Java or C++. See for humanoid robots: Robot Locomotion - JuliaHub

Java Minecraft isn’t going away, Microsoft released their build of JVM this year (not just for it): Announcing Microsoft Build of OpenJDK - Microsoft for Java Developers

Minecraft Java Edition also remains ubiquitous with a significant ecosystem of mods and a community of enthusiastic modders

There’s however also a C++ version (with missing features, i.e. modding missing?, I understand both versions may have pros and cons): Bedrock Edition – Minecraft Wiki

was created in the C++ programming language to run on platforms that cannot support Java.

4 Likes