The performance of setting properties by V8 C++ API is much worse than doing it in JS

59 views
Skip to first unread message

James Chen

unread,
Oct 16, 2022, 10:12:09 PM10/16/22
to v8-dev

Hello V8 team, thanks for making V8 engine which could run JavaScript super fast.

Recently, I want to improve the performance of deserialization for Cocos Creator game engine.

Cocos Creator uses V8 for its default JavaScript engine and benefited from V8's high performance. There're many classes implemented in JS and some implemented in C++. And there will be more and more JS code moved to C++ side.

I thought about deserializing game assets directly in C++ rather than in JS to get better performance since I think C++ code should be faster.

Therefore, I wrote a testcase to test whether we could get benefited from C++ code. But unfortunately, I got a really bad result saying that create JS object and setting properties in C++ by V8 API is really slower than doing that in JS. It's about 50 times slower, in another word, JS execution is really fast.

I debugged a little bit and found that the most heavy cost is in v8::Object::Set and v8::String::NewFromUtf8.

Part of JS test code:

const testArr = new Array<MySerializationTestClass>(this.loopCount);
        const start = performance.now();

        for (let i = 0; i < this.loopCount; ++i) {
            const test = new MySerializationTestClass();
            testArr[i] = test;

            test['booleanValue'] = false;
            test['nullValue'] = null;
            test['undefinedValue'] = undefined;
            test['numberValue0'] = 100.123;
            test['numberValue1'] = 230.2345;
            test['numberValue2'] = 330.2345;
            test['numberValue3'] = 430.2345;
            test['numberValue4'] = 530.2345;

            test['stringValue0'] = 'hello 0';

            test['stringValue1'] = 'hello 1';

The logic of CPP test code is the same as which in the above JS test code. The difference is that we use v8::Object::Set API.

### JIT Enabled

Cpp code is 55 times slower than JS code.

### JIT Disabled

Cpp code is 16 times slower than JS code.


### Xcode Profile


`v8::Maybe<bool> ret = _obj.handle(__isolate)->Set(__isolate->GetCurrentContext(), nameValue.ToLocalChecked(), value);` and `v8::String::NewFromUtf8` are the main hotspots.

### What I guess

I guess running JS code directly could make use of the optimization by V8 Bytecode and JIT by TurboFan. But invoking V8 C++ API will not get the optimization.


Could you point me out that whether my guess is correct or not? Also, is there a better V8 API for setting property?  Thanks.

 

Marja Hölttä

unread,
Oct 17, 2022, 1:59:35 AM10/17/22
to v8-...@googlegroups.com
Hi,

I didn't have a deep look, but your benchmarking might not be representative. 

1) V8 probably optimizes such a tight loop a lot (in the JIT mode). You're using string constants as property names, and V8 sees the whole object creation code at once, and can generate better optimized code. When we only need to do one v8::Object::Set, we can't do the same optimizations. (Very hand-wavy explanation; I didn't look at the actual generated code in this case.) If you make the object shape and property names + values more unpredictable (also if you make the benchmark closer to what your actual deserializer does), you might see a smaller difference. You'll also need to take into account the time needed for V8 to parse + compile the code, not only the JS execution time.

2) The string creation (for the property names) is done when we parse the JS code, so it's outside your benchmark timer. In your C++ version, I assume it's inside your benchmark timer.

The "16 times faster in the non-JIT mode" is a bit high though, I would've guessed the difference would be smaller.

Cheers,

--
--
v8-dev mailing list
v8-...@googlegroups.com
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to v8-dev+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/v8-dev/721fa65a-e310-4315-9166-e6beae89ce47n%40googlegroups.com.


--


Google Germany GmbH

Erika-Mann-Straße 33

80636 München


Geschäftsführer: Paul Manicle, Liana Sebastian.

Registergericht und -nummer: Hamburg, HRB 86891

Sitz der Gesellschaft: Hamburg


Diese E-Mail ist vertraulich. Falls sie diese fälschlicherweise erhalten haben sollten, leiten Sie diese bitte nicht an jemand anderes weiter, löschen Sie alle Kopien und Anhänge davon und lassen Sie mich bitte wissen, dass die E-Mail an die falsche Person gesendet wurde.

    

This e-mail is confidential. If you received this communication by mistake, please don't forward it to anyone else, please erase all copies and attachments, and please let me know that it has gone to the wrong person.

James Chen

unread,
Oct 17, 2022, 4:34:06 AM10/17/22
to v8-dev
Got it. I would modify my test code to see whether the result  could get better.

Thanks for your reply. :)

Jakob Kummerow

unread,
Oct 17, 2022, 5:54:34 AM10/17/22
to v8-...@googlegroups.com
In addition to what Marja said, I assume that a significant difference (even without JIT) is that JavaScript can use Inline Caches, whereas the API cannot.

James Chen

unread,
Oct 18, 2022, 5:04:22 AM10/18/22
to v8-dev
@Marja , According to your suggestion, I updated the test case with more random string access instead of const string. The new result is that CPP test case performs 2~3 times slower than JS test case now.

I posted more detail information at the end of  https://github.com/cocos/cocos-engine/issues/12878  here .

2~3 times slower is still not good enough for us to switch deserialization logic from JS to CPP. 
So, is 2~3 times slower expected ? Or are there more things I could do?

> In addition to what Marja said, I assume that a significant difference (even without JIT) is that JavaScript can use Inline Caches, whereas the API cannot.

@Jakob, Thank you for pointing me out that inline caches also make some optimizations.


Marja Hölttä

unread,
Oct 18, 2022, 6:02:52 AM10/18/22
to v8-...@googlegroups.com
I'd say at that point we're at the expected range of slowdown, given less optimization opportunities and no ICs when you go through the API.


--
--
v8-dev mailing list
v8-...@googlegroups.com
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to v8-dev+un...@googlegroups.com.

James Chen

unread,
Oct 18, 2022, 9:39:32 PM10/18/22
to v8-dev
Got it. Good to know this. Thanks a lot.
Reply all
Reply to author
Forward
0 new messages