New issue
Advanced search Search tips

Issue 619544 link

Starred by 3 users

Issue metadata

Status: WontFix
Owner: ----
Closed: Feb 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: 2
Type: Bug



Sign in to add a comment

Setting a large number of inline style properties seems regressed from M51 -> M53

Project Member Reported by esprehn@chromium.org, Jun 13 2016

Issue description

Google Chrome	53.0.2761.2 (Official Build) canary (64-bit)
Revision	605ae590e7a3e805a4dda7e9487caeb06827c8aa-refs/branch-heads/2761@{#3}

What steps will reproduce the problem?
(1) Load https://de.wikipedia.org/wiki/Cats (There's 1300 elements on this page).
(2) Open the devtools console
(3) Run:

t = performance.now(); document.querySelectorAll("*").forEach((e) => { e.style.transform = "rotate(2deg)" }); performance.now() - t;

(4) Run it repeatedly.

In 51.0.2704.63 I see: 10, 8, 8, 6, 6, ...

In 53.0.2761.2 (Official Build) canary (64-bit) I see: 14, 10, 11, 10, 9, ...

What changed that this seems to be slower? We've actually spent a bunch of time optimizing inline CSS setting, so this is especially surprising.

This seems regressed for all things though:

ex with color instead of transform, this is fast path only:

t = performance.now(); document.querySelectorAll("*").forEach((e) => { e.style.color = "red" }); performance.now() - t;

51.0.2704.63: 5, 2, 2, 3, ...
53.0.2761.2 Canary: 10, 7, 7, 7, ...

 
Components: -Blink>CSS Blink>JavaScript
Labels: -Pri-3 Pri-1
If you use a for loop this is the same between Canary and Stable, so it's either forEach or arrow functions that regressed to be much slower.

t = performance.now(); var e = document.querySelectorAll("*"); for (var i = 0; i < e.length; i++) { e[i].style.color = "red"; } performance.now() - t;
Cc: adamk@chromium.org

Comment 3 by adamk@chromium.org, Jun 13 2016

Components: -Blink>JavaScript Blink>JavaScript>Runtime
Owner: cbruni@chromium.org
Status: Assigned (was: Untriaged)
My only suspect is a change to forEach from the end of May: https://codereview.chromium.org/2013873002

cbruni, can you take a look? The interesting thing about this test case is that the receiver is not an Array, but rather a NodeList.

Comment 4 by cbruni@chromium.org, Jun 13 2016

Maybe IsArray was true for NodeList? This would be the only explanation for this regression.

Comment 5 by adamk@chromium.org, Jun 13 2016

Cc: haraken@chromium.org jochen@chromium.org cbruni@chromium.org
Components: -Blink>JavaScript>Runtime Blink>Bindings
Owner: ----
Status: Available (was: Assigned)
Turns out that NodeList.prototype.forEach !== Array.prototype.forEach, so cbruni's change is unrelated. The NodeList version is apparently implemented via the V8 API:

https://cs.chromium.org/chromium/src/third_party/WebKit/Source/bindings/core/v8/Iterable.h?q=iterable&sq=package:chromium&dr=CSs&l=42
https://cs.chromium.org/chromium/src/out/Debug/gen/blink/bindings/core/v8/V8NodeList.cpp?sq=package:chromium&dr=CSs&l=131

This code seems to have been added more than a year ago, in https://codereview.chromium.org/807263007

I don't see any recent changes in that method, so whatever got slow here likely got slow either elsewhere in the bindings layer or in the V8 API (or runtime).

But writing forEach using the V8 API is likely to be very slow in any case, due to the overhead of calling from C++ -> JS on every iteration.

Per WebIDL, it seems we're out of compliance here: forEach ought to be identical to Array.prototype.forEach (see http://heycam.github.io/webidl/#es-forEach).
Cc: yukishiino@chromium.org peria@chromium.org
+yukishiino +peria: Any idea?

https://codereview.chromium.org/1918763002/ touched the forEach binding, but I don't think it regressed performance...

I gave a shot with jl's CL reverted, and observed it didn't improve the performance.  Rather, it got worse with revert.

For Adam's point at #5, I've got surprised that it improved the performance very much.

t = performance.now(); Array.prototype.forEach.call(document.querySelectorAll("*"), (e) => { e.style.transform = "rotate(2deg)" }); performance.now() - t;

On my local env, it improved about 20-ish to 6-10 ish.

So, this is a very good point to improve NodeList.prototype.forEach().  However, it's not related to the original concern about the CSS's regression.


For the original question, we've added an extra type checking.
https://cs.chromium.org/chromium/src/out/Debug/gen/blink/bindings/core/v8/V8CSSStyleDeclaration.cpp?q=name-%3EIsString%5C(%5C)+case:yes+file:gen/blink/bindings/core/v8/V8CSSStyleDeclaration.cpp&sq=package:chromium&l=285
that was introduced by https://crrev.com/1993593003 (originally by https://crrev.com/1967453002 ).

Also note that, since |e.style.transform| is implemented as named properties, it may be affected by V8's implementation, too.

As far as I tested locally, name->IsString() check is not that expensive and the performance didn't change.  The official builds that are highly optimized would be more sensitive, though.

Comment 8 by peria@chromium.org, Aug 25 2016

Components: Blink>CSS
Labels: -Pri-1 Performance Pri-2
Components: -Blink>CSS
Blink>CSS has a policy of only having one component per bug (to avoid diffusion of responsibility). This looks like bindings is the team to take action next here.
Status: WontFix (was: Available)
https://crrev.com/2683853005 fixed NodeList.forEach.

Sign in to add a comment