slow function call in V8 when using the same key for the functions in different objects

后端 未结 2 757
Happy的楠姐
Happy的楠姐 2021-01-30 06:34

Maybe not because the call is slow, but rather the lookup is; I\'m not sure, but here is an example:

var foo = {};
foo.fn = function() {};

var bar = {};
bar.fn          


        
2条回答
  •  慢半拍i
    慢半拍i (楼主)
    2021-01-30 07:14

    Object literals share hidden class ("map" in v8 internal terms) by structure I.E. same named keys in same order, while objects created from different constructors would have different hidden class even if the constructors initialized them to exactly the same fields.

    When generating code for foo.fn(), in the compiler you don't generally have access to the specific foo object but only its hidden class. From the hidden class you could access the fn function but because the shared hidden class can actually have different function at the fn property, that is not possible. So because you don't know at compile time which function will be called, you cannot inline the call.

    If you run the code with trace inlining flag:

    $ /c/etc/iojs.exe --trace-inlining test.js
    t: 651ms
    

    However if you change anything so that either .fn is always the same function or foo and bar have different hidden class:

    $ /c/etc/iojs.exe --trace-inlining test.js
    Inlined foo.fn called from .
    t: 88ms
    

    (I did this by doing bar.asd = 3 before the bar.fn-assignment, but there are a ton of different ways to achieve it, such as constructors and prototypes which you surely know are the way to go for high performance javascript)

    To see what changed between versions, run this code:

    var foo = {};
    foo.fn = function() {};
    
    var bar = {};
    bar.fn = function() {};
    
    foo.fn();
    console.log("foo and bare share hidden class: ", %HaveSameMap(foo, bar));
    

    As you can see the results differs between node10 and iojs:

    $ /c/etc/iojs.exe --allow-natives-syntax test.js
    foo and bare share hidden class:  true
    
    $ node --allow-natives-syntax test.js
    foo and bare share hidden class:  false
    

    I haven't followed development of v8 in details recently so I couldn't point the exact reason but these kinds of heuristics change all the time in general.

    IE11 is closed source but from everything they have documented it actually seems like it's very similar to v8.

提交回复
热议问题