@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. 在2022年10月17日星期一 UTC+8 17:54:34<Jakob Kummerow> 写道: > 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. > > > On Mon, Oct 17, 2022 at 10:34 AM James Chen <[email protected]> wrote: > >> Got it. I would modify my test code to see whether the result could get >> better. >> >> Thanks for your reply. :) >> >> 在2022年10月17日星期一 UTC+8 13:59:35<[email protected]> 写道: >> >>> 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, >>> >>> On Mon, Oct 17, 2022 at 4:12 AM James Chen <[email protected]> wrote: >>> >>>> 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. >>>> >>> -- -- v8-dev mailing list [email protected] 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 [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/v8-dev/efc01cf2-8383-4034-abff-5a0d2cc54bd4n%40googlegroups.com.
