Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GDScript performance improvement via Just-in-time (JIT) compilation #5049

Closed
ghost opened this issue Jun 5, 2016 · 105 comments
Closed

GDScript performance improvement via Just-in-time (JIT) compilation #5049

ghost opened this issue Jun 5, 2016 · 105 comments

Comments

@ghost
Copy link

ghost commented Jun 5, 2016

What about adopting just-in-time (JIT) compilation for GDscripts?

JIT compilation has no disadvantages over interpreted code (aside from slower startup, in some cases) and many advantages, mainly in terms of performance.

For JIT compilation, there are at least two popular ways to implement it in a cross-platform way without writing any code from scratch:

There is also the option of using PyPy, the JVM or the CLR, but those are quite heavier, using GNU Lightning or libjit (not sure if the license is compatible with Godot's) and of course, writing a code generator from scratch (which could take years).

So, the choice is pretty much between LLVM IR and DynASM. Both have very good performance, but DynASM is written in Lua and LLVM has a fairly large footprint (~20MB), but also offers other features.

Of course, compiling GDScript directly to C++ could also be a valid alternative - the only game engine which does it that I know of (if I understood it correctly) is Enigma, which compiles its own scripting language (EDL) to C++.

What do you think about this?

@Calinou
Copy link
Member

Calinou commented Jun 5, 2016

JIT compilation has no disadvantages over interpreted code

There is one: portability…

But wouldn't implementing static typing be better and easier at least for now? Not to mention C# support which may eventually happen?

@bojidar-bg
Copy link
Contributor

@Calinou Portability isn't a big concern, since we could just run the GDScript as we do now on unsupported platforms.

@reduz
Copy link
Member

reduz commented Jun 5, 2016

static typing can be optionally jitted too

@ghost
Copy link
Author

ghost commented Jun 5, 2016

@Calinou portability isn't a big concern if those libraries are used - they support plenty of architectures (LLVM probably supports more architectures than Godot) and besides, the interpreter could always be used as a fallback (as @bojidar-bg said).

LLVM IR would actually make static typing easier to adopt (on the back-end, of course GDScript would still need either type inference or explicit type signatures).

If C# support is implemented by linking either against Mono or CoreCLR, those both include JITs so this issue will be solved automatically. I can understand why C# (it's a better language than Java and Unity already uses it) but for those purposes, the JVM would probably bring better performance than either Mono or CoreCLR (especially because of the JVM garbage collector, which is well suited for games since it doesn't freeze anything). After Java 8, I personally don't think most people would object to it instead of C# (as the advantages brought by C# at this point mostly come down to Generics and LINQ, both not as useful in game development, which is mostly imperative), and using the JVM gives access to plenty of neater functional languages than C# like Clojure, Scala and Kotlin anyway.

Also LLVM makes it possible to use C++ in a JITted fashion. Unreal Engine also uses C++ for scripting, so I don't think that would be too weird (provided segfaults will be more common, but GDScript could still be offered to less experienced programmers). C++14 (supported by LLVM for the most part) is quite a small language even compared to Java and C#, if used properly (of course, compile times are long and error messages are still not as good).

@Ace-Dragon
Copy link

I would support JIT compiling for GDscript as long as it doesn't mean the end of the language (or its respective built-in editor) as it is now,

My proposal.

  • Add a new static variable type, which in turn can be created by way of doing something like
    static var float(5.5) or something (the core difference would be higher performance and better parsing due to the expectation of it being a specific type. This method should allow the use of static typing while keeping the advantages of dynamic typing and eliminate any need for rewriting scripts if you want to use them
  • After that, add a JIT compiling routine that converts GDscript to C++ behind the scenes (ie. invisible to the user), but visible in the form of performance when the game is run. The idea of using C++ here would mean that the Godot developers would not have to add a bunch of new libraries to the source.

@reduz
Copy link
Member

reduz commented Jun 5, 2016

JIT in dynamically typed languages like Lua is done by doing type inference
from the entry point through the call tree, going as deep as possible. I'm
not saying this wouldn't be possible in Godot, as pretty much every entry
point is typed. The code completion in Godot does something similar, which
is why it's able to guess so much type information.

However there are many cases where the type is not obvious, and while the
code completion works great by guessing the get_node() calls on the tree
being edited, this information might be different or change in run-time.
I'm honestly not sure how efficient type inference might be.

To help on this, it would be easy to allow GDScript to allow the user to
"force" the type of a variable (something not possible in lua). But if you
are going to do this, then you might as well just go full static typing.

I'm not convinced of any approach at the moment.

On Sun, Jun 5, 2016 at 5:37 PM, Ace-Dragon notifications@github.com wrote:

I would support JIT compiling for GDscript as long as it doesn't mean the
end of the language (or its respective built-in editor) as it is now,

My proposal.

  • Add a new static variable type, which in turn can be created by
    way of doing something like
    static var float(5.5) or something (the core difference would be
    higher performance and better parsing due to the expectation of it being a
    specific type. This method should allow the use of static typing while
    keeping the advantages of dynamic typing and eliminate any need for
    rewriting scripts if you want to use them
  • After that, add a JIT compiling routine that converts GDscript to
    C++ behind the scenes (ie. invisible to the user), but visible in the form
    of performance when the game is run. The idea of using C++ here would mean
    that the Godot developers would not have to add a bunch of new libraries to
    the source.


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
#5049 (comment),
or mute the thread
https://github.com/notifications/unsubscribe/AF-Z2znHs58L-KDgtIjHYYjgHVUGXgwpks5qIzOngaJpZM4IuWZe
.

@Warlaan
Copy link
Contributor

Warlaan commented Jun 6, 2016

Haxe uses type inference even though it is type safe under the hood. Personally I like the fact that I don't have to define the type of every variable but that you can do so if you need it. That way you have the best of both worlds: you don't need to specify types (as long as the compiler can figure them out) and writing "generic"/"template" methods results in a much cleaner syntax as in statically typed languages like C++ or C#, but effectively the code is type safe and you can specify the requested type whenever you want to use it to make the code more readable.

In Haxe it's done using the syntax
var <name> [: <Type>] [=<initial value>]
which looks very weird coming from typed languages but makes perfect sense coming from a language like GDScript.

But I have no idea how this affects complexity and effectiveness of JIT compilation, I merely wanted to point out that this would be kind of a middle ground between dynamic typing as it is now and full static typing as it is in languages like C++.

@volzhs
Copy link
Contributor

volzhs commented Jun 6, 2016

I used Haxe for 1~2 years long time ago.
I like it to be able to define type optionally for variable and function return as @Warlaan said.

@bojidar-bg
Copy link
Contributor

I'd prefer the c++ type declaration style before the typescript/haxe one:

var x = 50
int y = 60
float z =70

Or maybe we could mirror export's style:

type(int) var y = 60
type(float) z =70

@kubecz3k
Copy link
Contributor

kubecz3k commented Jun 6, 2016

@bojidar-bg Personally I prefer c++ style more (a lot less typing).

@ghost
Copy link
Author

ghost commented Jun 6, 2016

There are a lot of issues that can arise from putting the type before the variable. Go was written by some of the most experienced C implementers ever (including Ken Thompson) and they went with Postfix notation (like Pascal and Haxe).

I think this discussion belongs in a separate discussion. I'm not proposing a vote because of course most people are used to typed languages like C++, C# and Java and could vote the familiar syntax but merely to gather research materials and opinions to find the solution that is best suited for a language like GDScript (which is clearly not C-like in any other aspect).

@Warlaan
Copy link
Contributor

Warlaan commented Jun 6, 2016

I agree in all four aspects:

  1. The C++-syntax is nicer to read, but
  2. imho the postfix notation makes more sense here
  3. which I would prefer to discuss (not decide by majority)
  4. in another thread. Sorry, I didn't mean to hijack the thread when I mentioned the topic. Let's return to the issue of JIT compilation.

@ghost
Copy link
Author

ghost commented Jun 6, 2016

Would implementing JIT via LLVM mean Clang would be preffered over GCC . Is it possible to compile LLVM JIT using GCC?

Unlike Java , Python, C# etc, GD Script works as part of a bigger C++ native code engine. In fact both GD Script & the rest of the engine are one unit. Some game components are C++ and some are GD Script. Overall the game performance depends on creating a balance between the two. Writing a Godot game solely in script would make it slower but writing it mostly via nodes with minimal gd script would make it faster.

So my question is . Is this small boost in performance really worth the effort?

I think C# addition may in fact be better for the engine than implementing JIT in GD Script. C# is probably much more optimized and efficient language thus probably as fast as GD Script + JIT but not as integrated as GD Script.

To answer my own question I personally don't see this being an important issue right now. Maybe in the future when Godot has all the desired features and devs would be simply optimizing those features.

@ghost
Copy link
Author

ghost commented Jun 7, 2016

Would implementing JIT via LLVM mean Clang would be preffered over GCC . Is it possible to compile LLVM JIT using GCC?

Yes, but then LLVM would become a dependency so it would make more sense to use LLVM for everything.

I don't think the boost in performance would be small for larger games. Maybe for arcade games it would not be noticeable, but in games with a lot of loops and function calls it definitely would.

Also, is there a discussion about why C# over Java or even C++? I think C# is a very good language, but the CLR and tooling is definitely inferior to the JVM (especially on other platforms than Windows).

@ghost
Copy link
Author

ghost commented Jun 7, 2016

@paper-pauper you should make a forum post about Java, JIT to continue this discussion. I'd actually prefer Java > C# tbh. I think C# was a not a choice but more of an opportunity that devs decided to take.

@ghost ghost mentioned this issue Jun 7, 2016
@ret80
Copy link

ret80 commented Jun 21, 2016

so that in the end we decided? will JIT or not?

@ghost
Copy link
Author

ghost commented Jun 21, 2016

How about the ability to compile GDScript to static C++ code? Would that even be possible?

@SuperUserNameMan
Copy link
Contributor

@trollworkout : it would probably be simpler and more optimized to write your game logic directly in C++ then, wouldn't it ?

@ghost
Copy link
Author

ghost commented Jun 21, 2016

@SuperUserNameMan Not necessarily. First you would be using C++ not GDScript and second you still need to figure out a way to load a binary object as a dll and plug it into the engine without having to recompile the engine with ur C++ changes.

@ghost
Copy link
Author

ghost commented Jun 21, 2016

@trollworkout Thanks to #3936 it could be possible to compile GDScript to C and load it dynamically, eventually.

@ret80
Copy link

ret80 commented Jun 21, 2016

it is not necessary to translate the script in c ++. @SuperUserNameMan rights

@ret80
Copy link

ret80 commented Jun 21, 2016

or need JIT or c# and all will be happy

@ghost
Copy link
Author

ghost commented Jun 21, 2016

nah the other topic @paper-pauper linked is actually much more interesting. The idea is to use C binary as a type of scripting language and call code directly via reflection rather than being interpreted making it as fast as C++ native code I think that would solve the ABI issue . In fact with this you don't need ABI anymore.

@brakhane
Copy link
Contributor

I am currently experimenting with implementing a GDScript JIT using RPython. The first (very preliminary) results are promising, but I don't know how hard it will be to integrate it into the engine.

Is there still interest in a JITed GDScript or are people more interesting in c# or static GDScript?

@Ace-Dragon
Copy link

Considering that you're actually trying out a possible solution, I say go for it and see if there's enough performance gain in games to be worth it.

What I mean by that is such a thing would only be worth pursuing if there's a rather large performance gain to be had for complex logic (or otherwise such gains might be better obtained from just doing general optimization work on the language itself).

@qiqian
Copy link

qiqian commented Aug 20, 2016

Performance is crucial for me, I just can't choose Godot for the script
Performance. But I think a faster language(Lua, Java, c#) is better than Jit, since Jit doesn't work on iOS. And compiling to c++ loses the possibility to update game logic on iOS

@mhilbrunner
Copy link
Member

@pchasco You may want to talk to @vnen, who is currently reworking GDScript for Godot 4.0 - IMO, this would be a good time to make sure to get such low-hanging fruit in :)

See https://godotengine.org/article/gdscript-progress-report-writing-tokenizer

@piratesephiroth
Copy link
Contributor

@pchasco You may want to talk to @vnen, who is currently reworking GDScript for Godot 4.0 - IMO, this would be a good time to make sure to get such low-hanging fruit in :)

See https://godotengine.org/article/gdscript-progress-report-writing-tokenizer

http://blog.moblcade.com/?p=114

@vnen
Copy link
Member

vnen commented May 12, 2020

Well, the VM is gonna change to integrate typed instructions so I'm not sure if doing optimization work now is the best. I do believe that those ideas can be used in the new VM, but it'll take a while until it's completed.

I'm not sure if we'll ever have JIT though, so maybe this issue could be closed in favor of something else. There's an idea of doing AOT compilation which would be easier to manage than this.

@mhilbrunner
Copy link
Member

@vnen Yeah the issue title isn't fitting anymore, if you read the above they found JIT not to be worth it mostly and instead went for targeted optimizations in the current interpreter.

It may be worthwhile to keep those in mind while reworking that, but yeah, you'll know way better than me when a good time is to see about those :) just wanted to connect you two

@pchasco
Copy link

pchasco commented May 12, 2020

http://blog.moblcade.com/?p=114

@pchasco You may want to talk to @vnen, who is currently reworking GDScript for Godot 4.0 - IMO, this would be a good time to make sure to get such low-hanging fruit in :)
See https://godotengine.org/article/gdscript-progress-report-writing-tokenizer

http://blog.moblcade.com/?p=114

I see you found my blog!

@pchasco
Copy link

pchasco commented May 12, 2020

Well, the VM is gonna change to integrate typed instructions so I'm not sure if doing optimization work now is the best. I do believe that those ideas can be used in the new VM, but it'll take a while until it's completed.

I'm not sure if we'll ever have JIT though, so maybe this issue could be closed in favor of something else. There's an idea of doing AOT compilation which would be easier to manage than this.

I agree that JIT is not a workable solution given the number of platforms, varying hardware, and amount of work necessary to maintain. AOT is definitely the simplest and the most portable solution for native performance with GDScript. In fact Unity transpiles .NET to C++ for its AOT also. I would be interested in contributing with the GDScript rewrite.

@mhilbrunner
Copy link
Member

@pchasco I'd suggest joining the #godotengine-devel IRC channel and get in contact there :)

@vnen
Copy link
Member

vnen commented Jun 2, 2020

As I mentioned before it's very unlikely that we'll add JIT. There are some other ideas in the discussion but no conclusion.

Since we are moving proposal to the GIP tracker, I'll close this one and if someone has an idea, please open a new proposal (after looking if nobody else did it first). This issue can be linked in relevant proposals to keep the discussion history.

Some contributors have different ideas for AOT compilation, but I'll let them open a proposal with what they have in mind.

@Teashrock
Copy link
Contributor

@vnen
Then please update the Roadmap, it's misleading people.

@vnen
Copy link
Member

vnen commented Aug 5, 2020

Well, I even forgot the roadmap existed, it isn't updated in a long time.

@Teashrock
Copy link
Contributor

@vnen
You forgot, but other users didn't. So please update it, because many are keeping it in mind.

@ghost
Copy link

ghost commented Aug 9, 2020

interpreters are garbage and to me that kills what usefulness gd script has when the performance is abysmal

you use an interpreter when you are writing a basic emulator, not a fully fledged game engine

a just in time compiler might often be faster than a slow, outdated ass compiler anyway, the interpreter system is just plain and simple bad, and i feel like i would rather rip out gd script and just go purely with c++, and just make a ghetto setup with a just in time system

i think people are not willing to admit that the interpreter is crap since people don't want to hurt each other feelings for some reason, but compared to c++, the end result is pretty, ehhh...

it's.... okay if you have something really basic going on i guess, but, for anything serious it's just, like it's not suitable for much of anything in my mind, beyond really simple games

@vnen
Copy link
Member

vnen commented Aug 9, 2020

@RaTcHeT302 no need to bring your negativity in and remember that we have a Code of Conduct. There are plans to optimize GDScript in many ways, including compilation to native code, just not with JIT. Also if you compare with C++ even a JITed runtime will be slow.

@Zireael07
Copy link
Contributor

Zireael07 commented Aug 9, 2020

@vnen: Just sayin' that LuaJIT is nearly up there with C/C++ on performance benchmarks - but there is a widespread belief that magic is involved 😄

@pchasco
Copy link

pchasco commented Aug 9, 2020 via email

@mnn
Copy link

mnn commented Aug 9, 2020

Aren't there downsides to AoT compared to JIT? For example what about dynamically generated or loaded scripts? JIT shouldn't have a problem optimizing them, but AoT?

By the way, on what major platform is not JIT possible? I thought Java with its JIT runs pretty much everywhere.

Edit: Oh, I guess Apple is the problem, the one prohibiting use of JIT. So it's an arbitrary vendor-lock limitation, not a technical one. Glad I don't have to support any Apple devices...

@pchasco
Copy link

pchasco commented Aug 9, 2020 via email

@neikeq
Copy link
Contributor

neikeq commented Aug 10, 2020

iOS, Web and a few console platforms do not support JIT compilation.

@Teashrock
Copy link
Contributor

Teashrock commented Sep 30, 2020

There's a rumor that AOT is now thrown out of the deck with JIT. I hope, that's not true. Somebody, please tell me, is it true?

@godotengine godotengine deleted a comment from Teashrock Sep 30, 2020
@pchasco
Copy link

pchasco commented Sep 30, 2020 via email

@Teashrock
Copy link
Contributor

@pchasco
No. I mean, somebody told me that GDScript will have neither AOT nor JIT.

@pchasco
Copy link

pchasco commented Sep 30, 2020 via email

@Teashrock
Copy link
Contributor

Teashrock commented Sep 30, 2020

@pchasco

maybe

So, you don't know. "Capable of supporting" doesn't mean "will support".

@Calinou
Copy link
Member

Calinou commented Sep 30, 2020

@Teashrock We don't know if GDScript will feature JIT or AOT compilation in 4.0, but it's not very likely. Maybe in 4.1 or later…

If you need higher performance for number crunching purposes (i.e. your CPU limitations clearly come from the scripting language), use C#. But first, read the optimization tutorials 🙂

@Teashrock
Copy link
Contributor

Teashrock commented Oct 1, 2020

@Calinou
It's just that they talked about 4.0 regarding JIT/AOT. And now you're saying me about 4.1. Why's that? How's that? Somebody, just give everyone a clear public anwser, which won't be somewhere deep on GitHub.

Thank you in advance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests