New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 771487 link

Starred by 1 user

Issue metadata

Status: Available
Owner: ----
Cc:
Components:
EstimatedDays: ----
NextAction: 2017-10-20
OS: Mac
Pri: 2
Type: Bug

Blocked on:
issue 764618



Sign in to add a comment

Oddly slow performance when appending empty, zero-sized elements

Reported by impinb...@gmail.com, Oct 4 2017

Issue description

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

Steps to reproduce the problem:
1. Run the benchmarks detailed below
2. Observe the newly added `span`s in the Devtools' "Elements" pane

What is the expected behavior?
Performance to be at least remotely close to Safari

What went wrong?
Safari is about 20x faster than Chrome

Did this work before? N/A 

Does this work in other browsers? Yes

Chrome version: 62.0.3202.38  Channel: beta
OS Version: OS X 10.12.6
Flash Version: Shockwave Flash 27.0 r0

Here's a reduced test case (run the first two benchmarks in Chrome and Safari):

https://jsperf.com/insertbefore-vs-appendchild/4

What it does is append empty `span`s to the page body below the window bottom. Chrome apparently tries to render these, where I suspect WebKit avoids this through occlusion culling of out-of-window elements.
 

Comment 1 Deleted

Comment 2 Deleted

Blockedon: 764618
Cc: jbroman@chromium.org
Components: -Blink>Compositing Blink>DOM

Comment 4 by woxxom@gmail.com, Oct 4 2017

FWIW I did some tests in Windows 7.

1. open the attached test.html
2. reload it a couple of times
Expected: tests complete in about 100ms
Observed: tests complete in about 500-1000ms

* Ten times slowdown in 58.0.3007.0
  test.html completes in 1000ms
  Bisect info: 448926 (good) - 448929 (bad)
  https://chromium.googlesource.com/chromium/src/+log/b66eb61f..17f5611f?pretty=fuller
  Suspecting r448928 "DOM: Remove standard-violating optimizations in appendChild, insertBefore, and replaceChild"
  Landed in 58.0.3007.0

* Regained half the speed in 62.0.3170.0 and 61.0.3163.25
  test.html completes in 500ms, which is still 5 times slower than before r448928 (58.0.3007.0)
  Bisect info: 490492 (bad) - 490511 (good)
  https://chromium.googlesource.com/chromium/src/+log/98e49f0d..e6754e43?pretty=fuller
  Suspecting r490502 "Don't ever check for fragment intersections when painting ancestor clipping"
  Landed in 62.0.3170.0
  Merged to 61.0.3163.25

* Regained bits of speed thanks to optimizations in issue 764618
  test.html completes in 400-500ms, which is still 4-5 times slower than before r448928 (58.0.3007.0)

test.html
873 bytes View Download
Cc: adithyas@chromium.org lfg@chromium.org

Comment 6 by kochi@chromium.org, Oct 6 2017

Cc: kochi@chromium.org
Labels: Performance
Owner: hayato@chromium.org
Status: Assigned (was: Unconfirmed)
impinb...@ thanks for the report.
woxxom@ thanks for the detailed regression analysis.

impinb...@ where did you see the "20x" difference between Chrome and Safari?
I tried the jsperf.com test that you provided, 
 - on OSX 10.12.6 Macbook Pro 13" 2016
 - Safari11.0 (12604,1.38.1.7)
 - Chrome 61.0.3163.100

What I saw in the results:
Chrome:
  - appendChild          1,847,297 ops/sec
  - insertBefore         1,801,330 ops/sec
  - ???                758,180,062 ops/sec
  - insertAdjacentHTML      56,830 ops/sec
  - insertAdjacentText   1,161,046 ops/sec
Safari:
  - appendChild          4,372,327 ops/sec
  - insertBefore         4,289,142 ops/sec
  - ???              1,819,242,570 ops/sec
  - insertAdjacentHTML     557,665 ops/sec
  - insertAdjacentText       1,437 ops/sec

Comment 7 by kochi@chromium.org, Oct 6 2017

Cc: hayato@chromium.org
Owner: ----
Status: Available (was: Assigned)
... and I see e.g. insertAdjacentHTML Safari is ~10x better than Chrome.

I see lots of "<span></span><span></span><span></span><span></span>..." below
the performance numbers table, and scrolling to the page bottom is quite
frustrating on Chrome, while it's very smooth in Safari.

This looks there are several issues mixed together, like in comment#4 pointed
out perf regression on appendChild() and similar APIs.  While the scrolling
issue is not directly the perf about DOM construction, but painting etc.

Comment 8 by kochi@chromium.org, Oct 6 2017

Labels: Needs-Feedback
impinb..@ could you let us know which part did you see 20x slower performance
on Chrome?

Comment 9 by kochi@chromium.org, Oct 6 2017

NextAction: 2017-10-20
The first two benchmarks in that. When I ran the Devtools profiler, it said
it was all spent in scripting. That's about the extent of my knowledge.
Thanks, then you saw significantly different number than I saw in comment 6?
The first two benchmarks (appendChild and insertBefore) are more than 2x slower,
but not more than 3x...  Could you paste raw number you see, and let us know
which Mac (e.g. Macbook core i5 x.yGHz etc.) is it?

Probably such DOM operations are slower in Chrome than in Safari, but we'd like
to know if there is any other factor that slows more down (e.g. other
background tabs, extensions, etc.) or purely coming from DOM code.
It's a mid-2012 Pro, with integrated Intel GPU, 2.7GHz CPU, and 8GB of RAM.
I had a few extra tabs open, but all the resource hogs (apart from Gitter)
were either killed or suspended via The Great Suspender (an extension). I
had two windows (one incognito) open, and I ran the tests in the incognito
window. It almost had 2GB to spare when I ran the tests, and the tests only
took a little over half a gig after it finished.
CPU was at a minimum, too, as I was monitoring the system via the Activity
Monitor built into macOS.

Comment 14 by kochi@chromium.org, Oct 11 2017

Thanks for the feedback!

I ran on my MBP (2016 13", 16GB, 3.3GHz Corei7) again and got similar numbers
as in comment #6.  While running the test I watched how things go in
ActivityMonitor, and during the test "Google Chrome Helper" process consumed
~100% CPU (this means Chrome's renderer (Blink) process ran using 100% CPU
for intensive loop of appendChild() etc.).  Despite the workload, CPU *graph*
on the Dock doesn't show 100%, maybe because the process hopped around cores
or HT threads (see screenshot for what I am talking about).

So I'm not sure about the comment #13 whether the CPU usage was really low
or not. It could have been due to 8 HT threads (I guess it's quad-core, 8 threads) and even with one CPU running at 100%, the system may look like
only 12.5% is used.  Or if something was blocking the renderer process from
running severely, it may explain the 20x slowdown.

From comment #12 I don't see any memory pressure situation, though.
screenshot.png
1.2 MB View Download
To clarify, CPU usage was low before/after the benchmark, not during. Sorry
about that.

Comment 16 by kochi@chromium.org, Oct 12 2017

Thanks for the clarification and sorry for my misunderstanding.
The NextAction date has arrived: 2017-10-20
Cc: erikc...@chromium.org
Labels: -Performance Performance-Loading Performance-Browser
This still seems like something we should dig into.
Project Member

Comment 19 by sheriffbot@chromium.org, Dec 13

Labels: Hotlist-Recharge-Cold
Status: Untriaged (was: Available)
This issue has been Available for over a year. If it's no longer important or seems unlikely to be fixed, please consider closing it out. If it is important, please re-triage the issue.

Sorry for the inconvenience if the bug really should have been left as Available.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Cc: fergal@chromium.org
Status: Available (was: Untriaged)
Moving this back to available and marking P3

Is there any reason to believe that this is an important case to optimize, i.e. that there is a significant amount of inserting empty spans going on. If not, it seems unlikely that anyone will ever optimize this case.
FWIW, just guessing, it might be still used by [many] legacy enterprise apps. As for modern DOM libraries and apps, those are usually smart enough to avoid innerHTML, build detached node trees and insert in one op, use DocumentFragment or Node#append and similar new methods to append an array of elements in one op. 

Sign in to add a comment