New issue
Advanced search Search tips

Issue 785166 link

Starred by 4 users

Issue metadata

Status: Fixed
Owner:
Closed: Jul 9
Components:
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: 3
Type: Bug



Sign in to add a comment

Consider optimizing innerHTML to skip the parser sometimes (especially for removing all children)

Project Member Reported by esprehn@chromium.org, Nov 15 2017

Issue description

Firefox has an optimization that actually checks to see if the string passed into innerHTML contains any html at all:
https://dxr.mozilla.org/mozilla-central/source/dom/base/FragmentOrElement.cpp#2493

https://dxr.mozilla.org/mozilla-central/search?q=%2Bcallers%3AnsINode%3A%3ASetHasWeirdParserInsertionMode%28%29

Looks like they disable the fast path for:

<head>, <html>, <select>, <template>, <frameset>, and all the table parts.

It's pretty common for authors to do innerHTML = '' to remove all the children of an element, but this invokes the parser and allocates a DocumentFragment a bunch of other data structures. We could make this much faster by noticing it's not a special element and just removing all the children like textContent = null would.

See also:
https://github.com/whatwg/dom/issues/478#issuecomment-344510087
 

Comment 1 by kochi@chromium.org, Nov 16 2017

Components: Blink>HTML>Parser

Comment 2 by kochi@chromium.org, Nov 16 2017

Status: Available (was: Untriaged)

Comment 3 by kochi@chromium.org, Nov 29 2017

Owner: rakina@chromium.org
Rakina, would you work on this?
Blocking: 793203

Comment 5 by rakina@chromium.org, Dec 14 2017

Blocking: -793203
Status: Started (was: Available)
CL for the specific case of innerHTML = '' is here crrev.com/c/813448.

It seems that Mozilla also optimizes for short strings without markups inside it and sets the length limit as 100 (searching for markup character is slow). We will do that in a separate CL, will compare performance between various length limits first.
Comparison between various length limits is here: https://docs.google.com/spreadsheets/d/1MJnSNUl6fSQgoGQtGcCOyAgP2u5rIuzBIGZ0TOW7m74/edit?usp=sharing

On speedometer, there aren't really a lot of difference between various length limits. I made a simple JS test here also: http://jsbin.com/yelahemisu/edit?html,console

On that test, innerHTML="" optimization (empty-string only optimization) speeds up the operation by 17x and makes almost every case faster except on strings with length >= 500, somehow. But they're all around 1-1.2x

When the change is only a few characters, all non-empty limit gives huge speedup (1 char string -> 5x speedup, 8 char string -> 8-9x speedup) but slows down by around 1.2x when the string has markup (fail to optimize)

When the limit is big (100, 500, infinite), changes of longer string with no markup (~100chars) experiences 4-5x speedup, but I'm not sure how often a long string with no markup will show up. It seems to peak around 100 chars, as the speedup on strings with no markup of length 500&1000 only sped up by around 2x.

If the string turns out to have markup, the slowdown is around 1.06x - 1.1x (I am not sure know how bad that is)

Anyone have any thoughts on this? I'm leaning towards a limit of >100.

Comment 7 by kochi@chromium.org, Jan 11 2018

Maybe this issue just reaches to those who follow this bug
(starred, owner of components, and the owner) - probably such discussion
could better happen at chromium-discuss@ or blink-dev@ to draw more
attention from those who are interested and get useful comments.

Comment 8 by rakina@chromium.org, Jan 18 2018

I started a discussion on blink-dev mailing list, and it seems the best way now is to only optimize for empty strings (innerHTML=''), but I will try to find a way to gather data round the short string optimization later.

Link to discussion: https://groups.google.com/a/chromium.org/d/msg/blink-dev/AUqsuLq70kA/YoM7iKD0AAAJ
Project Member

Comment 9 by bugdroid1@chromium.org, Jan 18 2018

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/b413fb498a9d6588ab431f7fd5c42ea707add52e

commit b413fb498a9d6588ab431f7fd5c42ea707add52e
Author: Rakina Zata Amni <rakina@chromium.org>
Date: Thu Jan 18 04:05:47 2018

Add optimization on InnerHTML setter when new string is empty

It's pretty common for authors to do innerHTML = '' to remove all the
children of an element, but this invokes the parser and allocates a
DocumentFragment a bunch of other data structures. We could make this
much faster by noticing it's not a special element and just removing
all the children like textContent = null would.

This change adds a check in InnerHTML setter so that when the new
string for innerHTML is empty we can just update its TextContent
instead of making a DocumentFragment and other unnecessary stuff
for this case.

Bug:  785166 
Change-Id: I29aaead811e820e7b38528efc3bfa3cce5bf7bab
Reviewed-on: https://chromium-review.googlesource.com/813448
Commit-Queue: Rakina Zata Amni <rakina@chromium.org>
Reviewed-by: Hayato Ito <hayato@chromium.org>
Reviewed-by: Kent Tamura <tkent@chromium.org>
Reviewed-by: Takayoshi Kochi <kochi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#530047}
[modify] https://crrev.com/b413fb498a9d6588ab431f7fd5c42ea707add52e/third_party/WebKit/Source/core/dom/Element.cpp
[modify] https://crrev.com/b413fb498a9d6588ab431f7fd5c42ea707add52e/third_party/WebKit/Source/core/dom/Element.h
[modify] https://crrev.com/b413fb498a9d6588ab431f7fd5c42ea707add52e/third_party/WebKit/Source/core/html/HTMLFrameSetElement.h
[modify] https://crrev.com/b413fb498a9d6588ab431f7fd5c42ea707add52e/third_party/WebKit/Source/core/html/HTMLHeadElement.h
[modify] https://crrev.com/b413fb498a9d6588ab431f7fd5c42ea707add52e/third_party/WebKit/Source/core/html/HTMLHtmlElement.h
[modify] https://crrev.com/b413fb498a9d6588ab431f7fd5c42ea707add52e/third_party/WebKit/Source/core/html/HTMLTableCaptionElement.h
[modify] https://crrev.com/b413fb498a9d6588ab431f7fd5c42ea707add52e/third_party/WebKit/Source/core/html/HTMLTableCellElement.h
[modify] https://crrev.com/b413fb498a9d6588ab431f7fd5c42ea707add52e/third_party/WebKit/Source/core/html/HTMLTableColElement.h
[modify] https://crrev.com/b413fb498a9d6588ab431f7fd5c42ea707add52e/third_party/WebKit/Source/core/html/HTMLTableElement.h
[modify] https://crrev.com/b413fb498a9d6588ab431f7fd5c42ea707add52e/third_party/WebKit/Source/core/html/HTMLTableRowElement.h
[modify] https://crrev.com/b413fb498a9d6588ab431f7fd5c42ea707add52e/third_party/WebKit/Source/core/html/HTMLTableSectionElement.h
[modify] https://crrev.com/b413fb498a9d6588ab431f7fd5c42ea707add52e/third_party/WebKit/Source/core/html/HTMLTemplateElement.h
[modify] https://crrev.com/b413fb498a9d6588ab431f7fd5c42ea707add52e/third_party/WebKit/Source/core/html/forms/HTMLSelectElement.h

Status: Fixed (was: Started)

Sign in to add a comment