Setting a large number of inline style properties seems regressed from M51 -> M53 |
|||||||
Issue descriptionGoogle 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, ...
,
Jun 13 2016
,
Jun 13 2016
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.
,
Jun 13 2016
Maybe IsArray was true for NodeList? This would be the only explanation for this regression.
,
Jun 13 2016
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).
,
Jun 13 2016
+yukishiino +peria: Any idea? https://codereview.chromium.org/1918763002/ touched the forEach binding, but I don't think it regressed performance...
,
Jun 15 2016
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.
,
Aug 25 2016
,
Feb 12 2017
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.
,
Feb 13 2017
|
|||||||
►
Sign in to add a comment |
|||||||
Comment 1 by esprehn@chromium.org
, Jun 13 2016Labels: -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;