LiquidPlayer/LiquidCore

Android: low performance in LiquidCore/nodejs compared to V8-only mode (factor >1000)

Znerole opened this issue · 1 comments

I had some debate on the performance of different ways of iterating over an array and decided to benchmark this. I also tried LiquidCore and found it to be several orders of magnitude slower than either a different node implementation for Android (https://github.com/JaneaSystems/nodejs-mobile) or Chrome on the same device. The release build of LiquidCore build is a bit faster than debug (factor 10, maybe), but still very slow.

In an attempt to isolate the issue, I tried the same benchmark with the V8-only mode using just the liquidcore-V8 module and it turns out to be much much faster, the main bottleneck now being calls to performance.now() which I substituted with a Java implementation. Removing this brings the performance to the same level as nodejs-mobile or Chrome.

So, apparently it had something to do with the way LiquidCore sets up nodejs.

I ran some profiling and found that 88% of the CPU time is spent by a call from PropertyCallbackArguments::BasicCallNamedGetterCallback (which is a v8 function) to OpaqueJSClass::NamedPropertyGetter (which is part of liquidcore-v8).

This is the flame graph:
image

Digging around, it appears to me that all property accesses are routed through the OpaqueJSClass, causing a severe performance bottleneck.

Unfortunately I'm out of my wits here and I find myself unable to work around or even fix this issue. Is OpaqueJSClass simply not optimized enough or is it too involved?

The benchmark is available on jsfiddle: https://jsfiddle.net/m0kpy1ju/
The javascript code runs either in the browser or standalone in nodejs (or LiquidCore).

I used the following code to setup my liquidcore-V8 instance:

        JSContext context = new JSContext();

        {
            // console somehow doesn't work right out of the box
            JSObject console = new JSObject(context);
            console.property("log", new JSFunction(context, "log") {
                public void log(String s) {
                    Log.i("V8", s);
                }
            });
            console.property("group", new JSFunction(context, "group") {
                public void group(String s) {
                    Log.i("V8", s);
                }
            });
            console.property("groupEnd", new JSFunction(context, "groupEnd") {
                public void groupEnd() {
                }
            });
            context.property("console", console);
        }
        {
            JSObject performance = new JSObject(context);
            performance.property("now", new JSFunction(context, "now") {
                public Long now() {
                    return System.currentTimeMillis();
                }
            });

            context.property("performance", performance);
        }

I tested LiquidCore 0.7.10 and also 0.6.1, both show the low performance.

Duplicate of #202