Hi Justin,
V8's hidden classes are not limited to tracking fields you assign to
an object, V8 also tries to capture methods you assign (just like in
any object-oriented language classes capture both data and behavior).
That is why first and second objects produced by Foobar will have
different hidden classes --- they have different methods.
As to your second question: they are not treated differently. If you
rewrite your test like this:
var z = {test: function () {}};
z.test2 = function () {};
function foo(z) {
var i;
console.time('test speed');
for (i = 0; i < 10000000; i++) z.test();
console.timeEnd('test speed');
console.time('test2 speed');
for (i = 0; i < 10000000; i++) z.test2();
console.timeEnd('test2 speed');
}
foo(z);
foo(z);
You will see something like:
test speed: 38ms
test2 speed: 12ms
test speed: 11ms
test2 speed: 11ms
Truth is V8 optimizes the code while the first loop is still _running_
(this is called On Stack Replacement aka OSR). So first "test speed"
measurement contains a sum of time spent in unoptimized code, compiler
and optimized code and first "test2 speed" measurement is purely time
spent in optimized code. If you call the same code second time you see
purely timing results for optimized code. This is why benchmarks
should always contain warm up phase to let optimizing JIT kick in.
Hope this explains it.
--
Vyacheslav Egorov
On Thu, Jul 19, 2012 at 3:04 AM, jMerliN <[email protected]> wrote:
> So I can't get my head around why this happens (I haven't dug through
> v8's code to try to figure it out either), but this is really
> inconsistent to me with how v8 constructs hidden classes in general.
> The following is running in Node.js v0.8.2 (V8 v3.11.10.12).
>
> Here's the code:
> http://pastebin.com/2gKWrfHp
>
> Here's the output, and the deopt trace:
> http://pastebin.com/WerQuGLZ
>
> Calling Foo.prototype.runTest with any Foo object results in similar
> performance (unless you change the hidden class, as expected). Bar
> expectedly deoptimizes because abc is stored on the proto and isn't
> actually on the constructed object until the first call, causing the
> optimized function (once it gets hot, which is after the object has
> changed hidden class) to bailout on the next attempt with a new Bar
> object.
>
> It gets weird with Foobar. test is added directly to the object, the
> only difference is that this is a function, not a primitive, but it
> seems like the hidden classes of objects from Foobar's constructor
> should be the same. The first run is performant, equivalent to Foo
> (expected). Though running the test again with a new Foobar
> deoptimizes it. I can't at all understand why.
>
> Thanks,
> Justin
>
> --
> v8-users mailing list
> [email protected]
> http://groups.google.com/group/v8-users
--
v8-users mailing list
[email protected]
http://groups.google.com/group/v8-users