QuickJS performance over legacy Juce javascript?

Hello,
I’m now trying to transition from Juce 7 to 8, and my software are heavily relying on users being able to create custom modules using javascript.

I’ve been finding bugs and posting issues and PR about them, but as I’m getting hopefully closer to something I can test with real scenarios, I’m getting the feeling that both compilation and function calls are slower than with the vanilla JUCE 7’s engine.

I’m a bit surprised about this since QuickJS is supposed to be more performant and optimized, but again this is just a feeling and I couldn’t really find any valuable information on that matter.

So I’m asking here if juce devs or other people have any insight about this ? This is quite an important information imho, as JUCE 8 is now the official version, but the javascript engine is really not production ready yet and if somehow it brings noticeably down performance and fluidity, I’d reconsider it, or I’d spend my time trying to integrate another scripting engine.

Thank you !

If you look under the hood, most of the calls into Juce Javascript API calls (execute and evaluate) involve string copying + parsing + executing, which is a pretty heavy taskload. My guess is that whatever optimizations QuickJS can do are pretty much negated by the fact that you have to parse on every call. I haven’t looked into it that deeply, but the Juce API for Javascript is quite small, so it doesn’t seem like there is much room to improve things by using the API more strategically.

I rely on scripting quite a lot also, and I decided to move over to the Spidermonkey library. It takes a while to set up (compiling it is a nightmare), but once the initial part is done, it works really smoothly, and is easy to debug. The API is also extremely flexible (more so than V8, I think). It’s a daunting task to transition, but one that I do not regret.

thank you for the feedback, so sad their call to move to QuickJS does seem the obvious best choice, I still hope other people can give positive feedback on that !
Do you have anything you’d be willing to share about spidermonkey’s implementation in juce ?
Even some performance feedback, my user’s modules are doing constant calls to the scripts so I’m looking for the fastest interpreter :slight_smile:

Do you have any benchmarks for comparison in release builds?

The big advantage of QuickJS over J7 is that it’s a much fuller JS implementation. There was so much you just couldn’t do with J7 but that is inevitably going to come with some cost.

I agree and i’d love to have an ESx compliant language, with includes, proper Math and everything ! But performance is key for me, and a slow full language is not better than a fast limited one.
I quickly tested minimal scripts :
I have an update function that is run in a separate thread to avoid any noise from the UI thread, and I’m stabilizing the calls at 100fps.

the JS function looks like that :

function update(deltaTime) {
for(var i=0;i<1000;i++) t = local.getChild("Parameters");

script.log(t,parseInt(1/deltaTime)+" fps");

}

So i’m running this loop x times to force a call to a native function that return an object based on its name. Then script.log will output to a UI logger (asynchronous), so it’s a 2nd C call, simpler.

with 100 loops :
Juce 7 : 100 fps,
Juce 8 : 100 fps

with 1000 loops :
Juce 7 : 100fps
Juce 8 : 80fps

with 10000 loops :
Juce 7 : 100fps
Juce 8 : 10fps

with 30000 loops:
Juce 7 : 100fps
Juce 8 : 1 fps

with 40000 loops:
Juce 7 : 80-90fps
Juce 8 : less than 1 fps.

as the “local” object already has a “parameter” property (that is the same as the one returned by the getChild() method), I replaced by local[“parameters”] and saw that Juce 8 can go up to 40k loops and keep its 100fps. The internal engine is fast but the calls and conversions are loosing quickly.

Additionnally, even with such a small code, Juce 8 will end up inevitably stopped with a wonderful and very verbose error : “interrupted”
I have to reload my script file that triggers a refresh of the engine to have it run again. This is another subject, but a quite important one as it renders the whole thing unusable right now.

EDIT : even this script get interrupted quite fast (few seconds after running it) :

function update(deltaTime) {
	for (var i = 0; i < 100; i++) {

	}
}

If you run a quick profiler, can you see an obvious hot spot?

string conversions were mentioned above. If that is most of the time, I’m wondering if some views or moves could massively speed things up.

I’m very happy to share whatever I have. I’ve a bunch of helper functions I built for converting types, compiling code, etc, and I can also share the binaries for windows x86 (it took me a month to get it compiled!) Before you go any further with it, check the license though, because as I understand the Mozilla public license requires you to make your source code public. But if you can live with that, Spidermonkey is a great option. Things like error handling, native functions, async code and custom proxies are well developed, and the api has function calls for pretty much anything you can dream of.

Even for general purpose that would be interesting to see how things are implemented for another engine !