New issue
Advanced search Search tips

Issue 666852 link

Starred by 17 users

Issue metadata

Status: Fixed
Owner:
Closed: Nov 2016
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Linux , Windows , Mac
Pri: 1
Type: Bug-Regression



Sign in to add a comment

Setting prototype properties is much slower in Chrome then other browsers

Reported by rgerb...@gmail.com, Nov 18 2016

Issue description

UserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.0 Safari/537.36

Steps to reproduce the problem:
Run the following code in Chrome and compare to Safari, Firefox, or Edge.

// code below
var body = {};
for (var i = 0; i < 150; i++){
    if (i % 3) {
        body['prop' + i] = 42;
    } else {
        body['method' + i] = function() {}
    }
}

function Base() {}
Base.prototype = {};

function run(fn, name) {
    var start = performance.now(),
        i, total, el;

    for(i = 0; i < 1000; i++) {
        fn();
    }

    total = performance.now() - start;
    el = document.createElement('div');
    el.innerHTML = name + ': ' + total.toFixed(2);
    document.body.appendChild(el);
}

function makeClass() {
    var ctor = function() {};
    var obj = {};
    ctor.prototype = Object.create(Base.prototype);
    var proto = ctor.prototype, name, fn;

    for(name in body){
        fn = body[name];
        if (typeof fn === 'function') {
            fn.$owner = ctor;
            fn.$name = name;
        }

        proto[name] = fn; // What is happening here?
    }

    return ctor;
}

run(makeClass, 'Class Maker');

What is the expected behavior?
Chrome is running as quickly as other browsers.

What went wrong?
Chrome is slow :( Sometimes even 12x slower :( :(

Did this work before? No 

Chrome version: 56.0.2924.0  Channel: canary
OS Version: OS X 10.12.1
Flash Version: Shockwave Flash 24.0 r0

Almost all the time seems to be in the line "proto[name] = fn;" 

FYI on my Macbook Pro I am seeing the following numbers

Chrome Version 56.0.2924.0 canary (64-bit) - 511ms
Safari Version 10.0.1 (12602.2.14.0.7) - 43ms
Firefox 50.0 - 83ms
 
Components: -Blink Blink>JavaScript
This is representative of what goes on loading a large application using a class construction library that operates on prototypes.
Saved code as a fiddle - https://jsfiddle.net/hnraoLej/1/

Microsoft Edge crushes it too.

Chrome 54.0.2840.99    -- 460.43
MS Edge 25.10586.672.0 -- 39.40

Edge is > 11x faster :(

Windows 10.0.10586 Build 10586
32 GB RAM
Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz, 3401 Mhz, 4 Core(s), 8 Logical Processor(s)

I believe this is regression, started with Chrome 43 - not sure what was changed there. Tested with https://jsfiddle.net/hnraoLej/1/

Chrome 41.0.2272.76  -- 98.00
Chrome 42.0.2311.90  -- 94.00
Chrome 43.0.2357.65  -- 405.00
Chrome 44.0.2403.125 -- 465.00
Chrome 45.0.2454.93  -- 496.00

Windows 10. It's tested using Sauce Labs. Not the best source for the performance tests but I tried to start several virtual machines with 42 and 43 to be sure.

This can be huge performance killer if used on large-scale! 

Comment 5 by ajha@chromium.org, Nov 22 2016

Labels: Needs-Bisect M-56

Comment 6 by jba...@implen.de, Nov 22 2016

Here are the timings from Embedded Linux with Qt 5.6.1, which initiated the whole investigation:
- Qt WebKit: 380 ms
- Qt WebEngine (based on Chromium 45): 3400 ms
Cc: jmukthavaram@chromium.org
Labels: -Type-Bug -Pri-2 -Needs-Bisect hasbisect OS-Linux OS-Windows Pri-1 Type-Bug-Regression
Owner: verwa...@chromium.org
Status: Assigned (was: Unconfirmed)
Able to reproduce the issue on windows 7, Linux Ubuntu 14.04 and Mac 10.11.6 using chrome canary 57.0.2926.0 version.

Please find the bisect information as below.

Narrow Bisect:

GOOD-43.0.2313.0-Revision--317570

BAD--43.0.2314.0-Revision--317781

You are probably looking for a change made after 317621 (known good), but no later than 317637 (first known bad).

CHANGELOG URL:

  https://chromium.googlesource.com/chromium/src/+log/ac997d3fdca4aff32e9c80779c
87dfd1e1a8e69b..8cf9caa44a6c41ca1df13a6e764ad430deb26901

Possible suspect:

https://chromium.googlesource.com/v8/v8/+/6e346dfc8435114a1c65e259060481c92e43a439

verwaest@could you please look into this issue if it is related to your change,else please route this to an appropriate dev person.

Thanks,
Cc: jkummerow@chromium.org
I'm aware of the issue. By now we should have most infrastructure in place to also make this particular pattern much better. I have a proposed fix (https://codereview.chromium.org/2525573002/) that will make it go from ~400 to ~50ms. We'll have to make sure that this doesn't inadvertently tank performance elsewhere though.
Project Member

Comment 9 by bugdroid1@chromium.org, Nov 22 2016

The following revision refers to this bug:
  https://chromium.googlesource.com/v8/v8.git/+/30d2fb6b509f44194ee5a6a7c1caa6b36fa61074

commit 30d2fb6b509f44194ee5a6a7c1caa6b36fa61074
Author: verwaest <verwaest@chromium.org>
Date: Tue Nov 22 13:24:53 2016

[runtime] Always normalize prototype maps that aren't marked as 'should be fast' yet

This makes the test in the bug ~10x faster. It could inadvertently make other things slower, so revert eagerly if included in a range where performance tanks.

BUG= chromium:666852 

Review-Url: https://codereview.chromium.org/2525573002
Cr-Commit-Position: refs/heads/master@{#41178}

[modify] https://crrev.com/30d2fb6b509f44194ee5a6a7c1caa6b36fa61074/src/objects.cc
[modify] https://crrev.com/30d2fb6b509f44194ee5a6a7c1caa6b36fa61074/test/mjsunit/fast-prototype.js

Status: Fixed (was: Assigned)
And Jakob's CL https://codereview.chromium.org/2504403005 now makes it run in ~17ms. I guess we can close this at ~25x speedup :)
Awesome stuff! No we can report bugs on Firefox, Safari and Edge that Chrome is 2x faster! :)

Comment 12 by jba...@implen.de, Nov 23 2016

Since Qt WebEngine is based on Chromium 45, I am not able to leverage from the huge improvement immediately. Instead, I just reverted the original changes in Chromium 43, which had caused a decrease in performance by >4x as confirmed by verwaest. Here is my change in v8/src/objects.cc line 9802:

  //if (mode == FAST_PROTOTYPE && PrototypeBenefitsFromNormalization(object)) {
  if (mode == FAST_PROTOTYPE && !object->map()->is_prototype_map()) {

Then I did a complete rebuild of Qt WebEngine.

Unfortunately, I do not see a performance improvement.

Do I miss something in order to backport this fix to Chromium 45?

Comment 13 by jba...@implen.de, Nov 25 2016

Actually, the commit https://chromium.googlesource.com/v8/v8/+/fade797d02a2c3da305004803eccc45ea9b103e2%5E%21/#F0 had been causing the initial performance bug. After reverting this in my Embedded Linux with Qt 5.6.1, I get the following timings:
- Qt WebKit: 380 ms
- Qt WebEngine: 3400 ms
- Qt WebEngine with fix: 650 ms
If you have control over the full stack, you could also just set up the prototype object installing it as prototype of the function. That way you get the best of both.

Comment 15 by jba...@implen.de, Dec 12 2016

Now I was able to compile the latest Chromium for my Embedded Linux and I get:
- Chromium 57.0.2948.0: 200 ms (almost double speed compared to Qt WebKit)

Sign in to add a comment