Optimizing innerHTML to skip the parser sometimes?

186 views
Skip to first unread message

Rakina Zata Amni

unread,
Jan 11, 2018, 3:44:10 AM1/11/18
to blink-dev
A while ago, we noticed that Firefox has an optimization that actually checks to see if the string passed into innerHTML contains any html, skipping the parsing stage if it doesn't and saving a lot of time by doing that. Details can be seen on crbug.com/785166

We currently have a CL that will be merged soon on crrev.com/c/813448, for the specific case of innerHTML='' (setting innerHTML as empty/removing all children). Mozilla's version, however, optimizes for strings with length under 100 (it's limited because making sure that the string doesn't contain any markup takes time).

I'm not sure why they chose 100 exactly, but I did some comparison of various length limits (0/empty strings only, 10, 50, 100, 500, infinite) applied to our version of the optimization, and the results are here: https://docs.google.com/spreadsheets/d/1hY59uTeMhJNUZsXuawJdo0AKurwWuxhCITP0oGtIhtA/edit?usp=sharing. I used Speedometer (http://browserbench.org/Speedometer/) and a self-made simple JS test (http://jsbin.com/yelahemisu).

Some of my interpretation of the data:
  • On speedometer: there aren't really a lot of difference between various length limits, though it seems the sweet spot is to limit it to really short strings around 10 characters.
  • On my JS test, all speedup are compared to vanilla/no optimization version: 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 the slowdowns are all around 1.06-1.1x.
  • When the change is only a few characters, all non-empty limit gives a sizeable 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, markup check already spent some time)
  • When the length 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 in real life. It also seems to peak around 100 chars, as the speedup on strings with no markup of length 500&1000 is only around 2x.
  • On most cases, 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)

With that, I'm asking for opinions from people in blink-dev. I'm not really sure about what length limit to choose, especially considering setting innerHTML to long strings with no markup might be a rare case. I'm also not sure about my intrepretation of the Speedometer result.

Any thoughts will be welcome! If my data sheet is not clear, I'll also be happy to clarify it.


Regards,


Rakina

Kentaro Hara

unread,
Jan 11, 2018, 3:54:01 AM1/11/18
to Rakina Zata Amni, Jeremy Roman, Lucas Gadani, Adithya Srinivasan, blink-dev
+Jeremy +Lucas + Adithya (who are looking into Speedometer optimization)


On Thu, Jan 11, 2018 at 5:44 PM, Rakina Zata Amni <rak...@chromium.org> wrote:
A while ago, we noticed that Firefox has an optimization that actually checks to see if the string passed into innerHTML contains any html, skipping the parsing stage if it doesn't and saving a lot of time by doing that. Details can be seen on crbug.com/785166

We currently have a CL that will be merged soon on crrev.com/c/813448, for the specific case of innerHTML='' (setting innerHTML as empty/removing all children). Mozilla's version, however, optimizes for strings with length under 100 (it's limited because making sure that the string doesn't contain any markup takes time).

This is a clever optimization! I really like it :)
 
I'm not sure why they chose 100 exactly, but I did some comparison of various length limits (0/empty strings only, 10, 50, 100, 500, infinite) applied to our version of the optimization, and the results are here: https://docs.google.com/spreadsheets/d/1hY59uTeMhJNUZsXuawJdo0AKurwWuxhCITP0oGtIhtA/edit?usp=sharing. I used Speedometer (http://browserbench.org/Speedometer/) and a self-made simple JS test (http://jsbin.com/yelahemisu).

It sounds like that you're just gaming micro-benchmarks. From that perspective, I don't have any strong opinion on this -- can we just choose one of the reasonable values (e.g., 100)? If you think that the number is critical for real-world applications, we can experiment with multiple numbers using Finch but I'm not sure if it's worth doing.




Some of my interpretation of the data:
  • On speedometer: there aren't really a lot of difference between various length limits, though it seems the sweet spot is to limit it to really short strings around 10 characters.
  • On my JS test, all speedup are compared to vanilla/no optimization version: 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 the slowdowns are all around 1.06-1.1x.
  • When the change is only a few characters, all non-empty limit gives a sizeable 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, markup check already spent some time)
  • When the length 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 in real life. It also seems to peak around 100 chars, as the speedup on strings with no markup of length 500&1000 is only around 2x.
  • On most cases, 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)

With that, I'm asking for opinions from people in blink-dev. I'm not really sure about what length limit to choose, especially considering setting innerHTML to long strings with no markup might be a rare case. I'm also not sure about my intrepretation of the Speedometer result.

Any thoughts will be welcome! If my data sheet is not clear, I'll also be happy to clarify it.


Regards,


Rakina

--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CACPC1r4Uu423MP%3Ded%2Buoo2N72BxxWaTtfO0fjhYC2ShdxneWxA%40mail.gmail.com.



--
Kentaro Hara, Tokyo, Japan

Daniel Vogelheim

unread,
Jan 11, 2018, 5:16:52 AM1/11/18
to Rakina Zata Amni, blink-dev
Some general feedback from having worked on the JavaScript parser: Micro-optimizations like these can pay off big-time, but they also have drawbacks in terms of code complexity, and in terms of "performance cliffs" (where a web developer makes an inconspicious change that pushes their code just outside of the optimization's pre-conditions and then performance tanks in mysterious ways). Moreover, they might be curing a symptom that would better be fixed in the underlying parser itself.

In this case: I'd assume that the HTML parser doesn't actually need to do a whole lot of work for a source string without markup. Like a custom does-this-contain-any-html check, it needs to skip to the beginning of the first tag or character entity, and that's fundamentally the same work as the custom check. If that bit of the parser can be made as fast as a custom version (and e.g. additiional initialization worked deferred to only where it's needed), then you'll likely end up with an optimization that applies more widely and is more "performance stable".



--

Ian Kilpatrick

unread,
Jan 11, 2018, 12:43:43 PM1/11/18
to Daniel Vogelheim, Rakina Zata Amni, blink-dev
One thing to keep in mind is that setting innerHTML is considered a dangerous anti-pattern if you are just setting the text content of the node. (You can just use textContent instead).
Are we able to change the speedometer benchmark to set the textContent instead if this is just plain text?

(The empty string optimization looks good however, and setTextContent already has a similar optimization).

Ian

To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CALG6KPPdY-ShP4wU6ac2LsBHGEM9R9pQpAVbFrtFkL_SBuU3hQ%40mail.gmail.com.

Kouhei Ueno

unread,
Jan 11, 2018, 12:46:34 PM1/11/18
to Ian Kilpatrick, Daniel Vogelheim, Rakina Zata Amni, blink-dev
On Fri, Jan 12, 2018 at 2:43 AM, Ian Kilpatrick <ikilp...@chromium.org> wrote:
One thing to keep in mind is that setting innerHTML is considered a dangerous anti-pattern if you are just setting the text content of the node. (You can just use textContent instead).
+1 
Are we able to change the speedometer benchmark to set the textContent instead if this is just plain text?

(The empty string optimization looks good however, and setTextContent already has a similar optimization).
+1
 
I'm supportive of taking this route: encourage authors to use textContent= instead, and have optimization path for empty string only.

Dave Tapuska

unread,
Jan 11, 2018, 2:08:24 PM1/11/18
to Kouhei Ueno, Ian Kilpatrick, Daniel Vogelheim, Rakina Zata Amni, blink-dev
Is this something that the HTML Parser can produce as output and you log a lighthouse warning/violation under these scenarios? That might a a way to encourage authors.

Daniel Bratell

unread,
Jan 11, 2018, 3:16:05 PM1/11/18
to Kouhei Ueno, Dave Tapuska, Ian Kilpatrick, Daniel Vogelheim, Rakina Zata Amni, blink-dev
There might be reasons for a script developer to use innerHTML for text since only innerHTML will decode character entities. Nudging a script developer to use the pure text path whenever such a string has no character entities sounds unhelpful since they might have to themselves scan the string in JS before selecting what property to set.

I think the optimization to not start the HTML parser for pure text makes a lot of sense. Whether to scan 64 chars (Presto), 100 chars (Mozilla) or some other number I think don't matter except possibly for some benchmark. 

/Daniel

Ian

To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.



--
kouhei
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAHXv1wkeYLhCpM%2BL_Dyzh0-sYn0BVj84KxMBMiF8t3rjXXsQ8A%40mail.gmail.com.



--
/* Opera Software, Linköping, Sweden: CET (UTC+1) */

Rakina Zata Amni

unread,
Jan 12, 2018, 1:32:53 AM1/12/18
to Daniel Bratell, Kouhei Ueno, Dave Tapuska, Ian Kilpatrick, Daniel Vogelheim, blink-dev, tk...@chromium.org
Thanks for all the replies so far!
It sounds like that you're just gaming micro-benchmarks. From that perspective, I don't have any strong opinion on this -- can we just choose one of the reasonable values (e.g., 100)? If you think that the number is critical for real-world applications, we can experiment with multiple numbers using Finch but I'm not sure if it's worth doing.
I see, it seems like if we choose to optimize for non-empty string, an arbitrary length limit can be chosen. 

Some general feedback from having worked on the JavaScript parser: Micro-optimizations like these can pay off big-time, but they also have drawbacks in terms of code complexity, and in terms of "performance cliffs" (where a web developer makes an inconspicious change that pushes their code just outside of the optimization's pre-conditions and then performance tanks in mysterious ways). Moreover, they might be curing a symptom that would better be fixed in the underlying parser itself.
In this case: I'd assume that the HTML parser doesn't actually need to do a whole lot of work for a source string without markup. Like a custom does-this-contain-any-html check, it needs to skip to the beginning of the first tag or character entity, and that's fundamentally the same work as the custom check. If that bit of the parser can be made as fast as a custom version (and e.g. additiional initialization worked deferred to only where it's needed), then you'll likely end up with an optimization that applies more widely and is more "performance stable".
I see, it might be bad to confuse web developers when minor changes inexplicably drops performance. But, I've talked to tkent@ (cc'ed) from HTML team and it seems like it is better to do the check before firing the parser, because we can't skip some expensive operation like creating DocumentFragment.
 
One thing to keep in mind is that setting innerHTML is considered a dangerous anti-pattern if you are just setting the text content of the node. (You can just use textContent instead). 
I'm supportive of taking this route: encourage authors to use textContent= instead, and have optimization path for empty string only.
Hmm, I guess not optimizing non-empty strings might help drive away developers from using it instead of setTextContent (because it's slower), but I'm not sure if they'll stop using it with just that.

There might be reasons for a script developer to use innerHTML for text since only innerHTML will decode character entities. Nudging a script developer to use the pure text path whenever such a string has no character entities sounds unhelpful since they might have to themselves scan the string in JS before selecting what property to set.
I think the optimization to not start the HTML parser for pure text makes a lot of sense. Whether to scan 64 chars (Presto), 100 chars (Mozilla) or some other number I think don't matter except possibly for some benchmark. 
Yeah, this is one of the cases that makes me unsure if we should optimize empty strings only or non-markuped strings as well.

Is this something that the HTML Parser can produce as output and you log a lighthouse warning/violation under these scenarios? That might a a way to encourage authors.
 By lighthouse warning, do you mean have a warning line pop up in DevTools? It might be possible, but is it OK to do that?

Summarizing, I'm still unsure whether or not to optimize for empty string only or also optimize for reasonably short strings as well. Not optimizing might be a good thing to simplify the check and drive away people from inappropriate innerHTML usage, but there are some valid use cases that might benefit from the optimization. Does anybody know a way to know how people are actually using innerHTML setter?


Regards,

Rakina


Ian

To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.



--
kouhei
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.

PhistucK

unread,
Jan 12, 2018, 3:02:10 AM1/12/18
to Rakina Zata Amni, Daniel Bratell, Kouhei Ueno, Dave Tapuska, Ian Kilpatrick, Daniel Vogelheim, blink-dev, TAMURA, Kent
Will this non-empty-but-short optimization code path support HTML entities, or are they considered markup as well?


PhistucK

Rakina Zata Amni

unread,
Jan 12, 2018, 3:06:55 AM1/12/18
to PhistucK, Daniel Bratell, Kouhei Ueno, Dave Tapuska, Ian Kilpatrick, Daniel Vogelheim, blink-dev, TAMURA, Kent
Will this non-empty-but-short optimization code path support HTML entities, or are they considered markup as well?

They are considered markup as well, and will be sent back for parsing.

Ian Kilpatrick

unread,
Jan 12, 2018, 5:25:05 PM1/12/18
to Rakina Zata Amni, PhistucK, Daniel Bratell, Kouhei Ueno, Dave Tapuska, Daniel Vogelheim, blink-dev, TAMURA, Kent
I quickly looked at the benchmark source. Are you able to rerun your patch and report back on the individual timings for each type of framework? (for the non-empty optimization).
(You can do this on the InteractiveRunner.html page, i.e. http://browserbench.org/Speedometer/InteractiveRunner.html )


Rakina Zata Amni

unread,
Jan 15, 2018, 7:31:16 AM1/15/18
to Ian Kilpatrick, PhistucK, Daniel Bratell, Kouhei Ueno, Dave Tapuska, Daniel Vogelheim, blink-dev, TAMURA, Kent
Here is the result:
Optimizing strings under 100 characters:
VanillaJS-TodoMVC : Adding100Items : Sync: 135.69999998435378 ms
VanillaJS-TodoMVC : Adding100Items : Async: 75.30000002589077 ms
VanillaJS-TodoMVC : CompletingAllItems : Sync: 76.19999995222315 ms
VanillaJS-TodoMVC : CompletingAllItems : Async: 24.70000000903383 ms
VanillaJS-TodoMVC : DeletingAllItems : Sync: 50.40000000735745 ms
VanillaJS-TodoMVC : DeletingAllItems : Async: 4.100000020116568 ms
VanillaJS-TodoMVC : 366.39999999897555 ms
EmberJS-TodoMVC : Adding100Items : Sync: 457.2000000043772 ms
EmberJS-TodoMVC : Adding100Items : Async: 21.099999954458326 ms
EmberJS-TodoMVC : CompletingAllItems : Sync: 224.10000005038455 ms
EmberJS-TodoMVC : CompletingAllItems : Async: 20.700000051874667 ms
EmberJS-TodoMVC : DeletingItems : Sync: 271.8999999924563 ms
EmberJS-TodoMVC : DeletingItems : Async: 4.799999995157123 ms
EmberJS-TodoMVC : 999.8000000487082 ms
BackboneJS-TodoMVC : Adding100Items : Sync: 129.89999999990687 ms
BackboneJS-TodoMVC : Adding100Items : Async: 19.59999999962747 ms
BackboneJS-TodoMVC : CompletingAllItems : Sync: 125.89999998454005 ms
BackboneJS-TodoMVC : CompletingAllItems : Async: 18.999999971129 ms
BackboneJS-TodoMVC : DeletingAllItems : Sync: 126.50000001303852 ms
BackboneJS-TodoMVC : DeletingAllItems : Async: 4.499999980907887 ms
BackboneJS-TodoMVC : 425.3999999491498 ms
jQuery-TodoMVC : Adding100Items : Sync: 250.69999997504056 ms
jQuery-TodoMVC : Adding100Items : Async: 20.900000003166497 ms
jQuery-TodoMVC : CompletingAllItems : Sync: 476.8000000040047 ms
jQuery-TodoMVC : CompletingAllItems : Async: 28.799999970942736 ms
jQuery-TodoMVC : DeletingAllItems : Sync: 8.7000000057742 ms
jQuery-TodoMVC : DeletingAllItems : Async: 16.500000027008355 ms
jQuery-TodoMVC : 802.399999985937 ms
AngularJS-TodoMVC : Adding100Items : Sync: 309.9999999976717 ms
AngularJS-TodoMVC : Adding100Items : Async: 24.200000043492764 ms
AngularJS-TodoMVC : CompletingAllItems : Sync: 186.19999999646097 ms
AngularJS-TodoMVC : CompletingAllItems : Async: 19.100000034086406 ms
AngularJS-TodoMVC : DeletingAllItems : Sync: 217.99999999348074 ms
AngularJS-TodoMVC : DeletingAllItems : Async: 5.800000042654574 ms
AngularJS-TodoMVC : 763.3000001078472 ms
React-TodoMVC : Adding100Items : Sync: 387.30000000214204 ms
React-TodoMVC : Adding100Items : Async: 27.800000039860606 ms
React-TodoMVC : CompletingAllItems : Sync: 422.2000000299886 ms
React-TodoMVC : CompletingAllItems : Async: 19.19999998062849 ms
React-TodoMVC : DeletingAllItems : Sync: 198.7000000081025 ms
React-TodoMVC : DeletingAllItems : Async: 4.799999995157123 ms
React-TodoMVC : 1060.0000000558794 ms
FlightJS-TodoMVC : Adding100Items : Sync: 89.09999998286366 ms
FlightJS-TodoMVC : Adding100Items : Async: 18.80000001983717 ms
FlightJS-TodoMVC : CompletingAllItems : Sync: 88.09999999357387 ms
FlightJS-TodoMVC : CompletingAllItems : Async: 31.299999973271042 ms
FlightJS-TodoMVC : DeletingAllItems : Sync: 108.30000002169982 ms
FlightJS-TodoMVC : DeletingAllItems : Async: 4.099999961908907 ms
FlightJS-TodoMVC : 339.6999999531545 ms
FlightJS-MailClient : OpeningTabs50Times : Sync: 246.90000002738088 ms
FlightJS-MailClient : OpeningTabs50Times : Async: 16.299999959301203 ms
FlightJS-MailClient : MovingEmails50Times : Sync: 1023.700000019744 ms
FlightJS-MailClient : MovingEmails50Times : Async: 20.699999993667006 ms
FlightJS-MailClient : Sending50NewEmails : Sync: 110.99999997531995 ms
FlightJS-MailClient : Sending50NewEmails : Async: 4.200000024866313 ms
FlightJS-MailClient : 1422.8000000002794 ms
Total : 6179.800000099931 ms

For comparison, optimization for empty string only:
VanillaJS-TodoMVC : Adding100Items : Sync: 118.59999998705462 ms
VanillaJS-TodoMVC : Adding100Items : Async: 17.80000003054738 ms
VanillaJS-TodoMVC : CompletingAllItems : Sync: 63.199999975040555 ms
VanillaJS-TodoMVC : CompletingAllItems : Async: 27.200000011362135 ms
VanillaJS-TodoMVC : DeletingAllItems : Sync: 52.099999971687794 ms
VanillaJS-TodoMVC : DeletingAllItems : Async: 4.200000024866313 ms
VanillaJS-TodoMVC : 283.1000000005588 ms
EmberJS-TodoMVC : Adding100Items : Sync: 438.4999999892898 ms
EmberJS-TodoMVC : Adding100Items : Async: 17.99999998183921 ms
EmberJS-TodoMVC : CompletingAllItems : Sync: 207.69999996991828 ms
EmberJS-TodoMVC : CompletingAllItems : Async: 14.699999999720603 ms
EmberJS-TodoMVC : DeletingItems : Sync: 262.700000021141 ms
EmberJS-TodoMVC : DeletingItems : Async: 4.899999999906868 ms
EmberJS-TodoMVC : 946.4999999618158 ms
BackboneJS-TodoMVC : Adding100Items : Sync: 162.10000001592562 ms
BackboneJS-TodoMVC : Adding100Items : Async: 32.69999998155981 ms
BackboneJS-TodoMVC : CompletingAllItems : Sync: 168.40000002412125 ms
BackboneJS-TodoMVC : CompletingAllItems : Async: 18.59999995213002 ms
BackboneJS-TodoMVC : DeletingAllItems : Sync: 141.2999999593012 ms
BackboneJS-TodoMVC : DeletingAllItems : Async: 4.200000024866313 ms
BackboneJS-TodoMVC : 527.2999999579042 ms
jQuery-TodoMVC : Adding100Items : Sync: 206.6999999806285 ms
jQuery-TodoMVC : Adding100Items : Async: 20.299999974668026 ms
jQuery-TodoMVC : CompletingAllItems : Sync: 485.99999997531995 ms
jQuery-TodoMVC : CompletingAllItems : Async: 22.200000006705523 ms
jQuery-TodoMVC : DeletingAllItems : Sync: 8.199999982025474 ms
jQuery-TodoMVC : DeletingAllItems : Async: 4.199999966658652 ms
jQuery-TodoMVC : 747.5999998860061 ms
AngularJS-TodoMVC : Adding100Items : Sync: 321.50000002002344 ms
AngularJS-TodoMVC : Adding100Items : Async: 25.10000002803281 ms
AngularJS-TodoMVC : CompletingAllItems : Sync: 209.20000004116446 ms
AngularJS-TodoMVC : CompletingAllItems : Async: 31.399999978020787 ms
AngularJS-TodoMVC : DeletingAllItems : Sync: 193.09999997494742 ms
AngularJS-TodoMVC : DeletingAllItems : Async: 5.899999989196658 ms
AngularJS-TodoMVC : 786.2000000313856 ms
React-TodoMVC : Adding100Items : Sync: 351.29999998025596 ms
React-TodoMVC : Adding100Items : Async: 21.500000031664968 ms
React-TodoMVC : CompletingAllItems : Sync: 401.1000000173226 ms
React-TodoMVC : CompletingAllItems : Async: 18.999999971129 ms
React-TodoMVC : DeletingAllItems : Sync: 230.19999999087304 ms
React-TodoMVC : DeletingAllItems : Async: 4.799999995157123 ms
React-TodoMVC : 1027.8999999864027 ms
FlightJS-TodoMVC : Adding100Items : Sync: 93.90000003622845 ms
FlightJS-TodoMVC : Adding100Items : Async: 19.099999975878745 ms
FlightJS-TodoMVC : CompletingAllItems : Sync: 73.19999998435378 ms
FlightJS-TodoMVC : CompletingAllItems : Async: 19.099999975878745 ms
FlightJS-TodoMVC : DeletingAllItems : Sync: 76.99999999022111 ms
FlightJS-TodoMVC : DeletingAllItems : Async: 4.399999976158142 ms
FlightJS-TodoMVC : 286.699999938719 ms
FlightJS-MailClient : OpeningTabs50Times : Sync: 248.39999998221174 ms
FlightJS-MailClient : OpeningTabs50Times : Async: 9.90000000456348 ms
FlightJS-MailClient : MovingEmails50Times : Sync: 848.3999999589287 ms
FlightJS-MailClient : MovingEmails50Times : Async: 21.999999997206032 ms
FlightJS-MailClient : Sending50NewEmails : Sync: 111.70000000856817 ms
FlightJS-MailClient : Sending50NewEmails : Async: 4.199999966658652 ms
FlightJS-MailClient : 1244.5999999181367 ms
Total : 5849.899999680929 ms

and no optimization:
VanillaJS-TodoMVC : Adding100Items : Sync: 126.80000002728775 ms
VanillaJS-TodoMVC : Adding100Items : Async: 73.7000000081025 ms
VanillaJS-TodoMVC : CompletingAllItems : Sync: 48.69999998481944 ms
VanillaJS-TodoMVC : CompletingAllItems : Async: 17.699999967589974 ms
VanillaJS-TodoMVC : DeletingAllItems : Sync: 30.499999993480742 ms
VanillaJS-TodoMVC : DeletingAllItems : Async: 4.100000020116568 ms
VanillaJS-TodoMVC : 301.500000001397 ms
EmberJS-TodoMVC : Adding100Items : Sync: 389.39999998547137 ms
EmberJS-TodoMVC : Adding100Items : Async: 20.39999997941777 ms
EmberJS-TodoMVC : CompletingAllItems : Sync: 150.09999996982515 ms
EmberJS-TodoMVC : CompletingAllItems : Async: 16.500000027008355 ms
EmberJS-TodoMVC : DeletingItems : Sync: 250.2000000094995 ms
EmberJS-TodoMVC : DeletingItems : Async: 4.099999961908907 ms
EmberJS-TodoMVC : 830.699999933131 ms
BackboneJS-TodoMVC : Adding100Items : Sync: 119.69999998109415 ms
BackboneJS-TodoMVC : Adding100Items : Async: 19.499999994877726 ms
BackboneJS-TodoMVC : CompletingAllItems : Sync: 122.2999999881722 ms
BackboneJS-TodoMVC : CompletingAllItems : Async: 19.00000002933666 ms
BackboneJS-TodoMVC : DeletingAllItems : Sync: 90.10000003036112 ms
BackboneJS-TodoMVC : DeletingAllItems : Async: 4.199999966658652 ms
BackboneJS-TodoMVC : 374.7999999905005 ms
jQuery-TodoMVC : Adding100Items : Sync: 177.800000004936 ms
jQuery-TodoMVC : Adding100Items : Async: 16.39999996405095 ms
jQuery-TodoMVC : CompletingAllItems : Sync: 322.1000000485219 ms
jQuery-TodoMVC : CompletingAllItems : Async: 16.79999998304993 ms
jQuery-TodoMVC : DeletingAllItems : Sync: 3.700000001117587 ms
jQuery-TodoMVC : DeletingAllItems : Async: 5.499999970197678 ms
jQuery-TodoMVC : 542.2999999718741 ms
AngularJS-TodoMVC : Adding100Items : Sync: 217.09999995073304 ms
AngularJS-TodoMVC : Adding100Items : Async: 17.500000016298145 ms
AngularJS-TodoMVC : CompletingAllItems : Sync: 105.50000000512227 ms
AngularJS-TodoMVC : CompletingAllItems : Async: 15.000000013969839 ms
AngularJS-TodoMVC : DeletingAllItems : Sync: 115.49999995622784 ms
AngularJS-TodoMVC : DeletingAllItems : Async: 4.200000024866313 ms
AngularJS-TodoMVC : 474.79999996721745 ms
React-TodoMVC : Adding100Items : Sync: 337.4000000185333 ms
React-TodoMVC : Adding100Items : Async: 25.29999997932464 ms
React-TodoMVC : CompletingAllItems : Sync: 400.80000000307336 ms
React-TodoMVC : CompletingAllItems : Async: 20.499999984167516 ms
React-TodoMVC : DeletingAllItems : Sync: 240.300000004936 ms
React-TodoMVC : DeletingAllItems : Async: 4.599999985657632 ms
React-TodoMVC : 1028.8999999756925 ms
FlightJS-TodoMVC : Adding100Items : Sync: 118.40000003576279 ms
FlightJS-TodoMVC : Adding100Items : Async: 29.29999999469146 ms
FlightJS-TodoMVC : CompletingAllItems : Sync: 111.90000001806766 ms
FlightJS-TodoMVC : CompletingAllItems : Async: 23.400000005494803 ms
FlightJS-TodoMVC : DeletingAllItems : Sync: 82.50000001862645 ms
FlightJS-TodoMVC : DeletingAllItems : Async: 4.499999980907887 ms
FlightJS-TodoMVC : 370.00000005355105 ms
FlightJS-MailClient : OpeningTabs50Times : Sync: 329.00000002700835 ms
FlightJS-MailClient : OpeningTabs50Times : Async: 17.99999998183921 ms
FlightJS-MailClient : MovingEmails50Times : Sync: 1162.5999999814667 ms
FlightJS-MailClient : MovingEmails50Times : Async: 44.200000003911555 ms
FlightJS-MailClient : Sending50NewEmails : Sync: 183.49999998463318 ms
FlightJS-MailClient : Sending50NewEmails : Async: 20.699999993667006 ms
FlightJS-MailClient : 1757.999999972526 ms
Total : 5680.99999986589 ms


Daniel Bratell

unread,
Jan 15, 2018, 11:33:58 AM1/15/18
to Ian Kilpatrick, Rakina Zata Amni, PhistucK, Kouhei Ueno, Dave Tapuska, Daniel Vogelheim, blink-dev, TAMURA, Kent
The results look strange. Too big differences and the optimized code is significantly slower. I suspect your computer wasn't performing the same way for every test run (background tasks, CPU burst modes, ...). It really is hard to see the effect of changes with as small impact as this without micro benchmarks and a stable test platform.

To get an idea how innerHTML is used normally, maybe you can log it and browse a bit locally. It will not be scientific but might give an idea for how common it is to send short text strings to innerHTML. The alternative is to study databases of source code which I think will be unhelpful, or to insert some UMA data collector and I don't think that is necessary.

/Daniel


PhistucK


Ian

To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.



--
kouhei
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.



--
/* Opera Software, Linköping, Sweden: CET (UTC+1) */
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.

Lucas Gadani

unread,
Jan 15, 2018, 2:42:37 PM1/15/18
to Rakina Zata Amni, Ian Kilpatrick, PhistucK, Daniel Bratell, Kouhei Ueno, Dave Tapuska, Daniel Vogelheim, blink-dev, TAMURA, Kent
(sorry, re-sending from the correct email).

Your numbers here look like a significant regression, so I'm guessing there must be something wrong with your testing environment.

Can you try running the benchmarks on the perf bots? Try using a  --pageset-repeat of around 200-300 for Speedometer, it'll typically run in 4-5 hours.

The other test that I usually use for innerHTML parsing is blink_perf.parser textarea-parsing (https://cs.chromium.org/chromium/src/third_party/WebKit/PerformanceTests/Parser/textarea-parsing.html), but with your change it likely won't affect it much, though it's still useful to know if it regresses.


On Mon, Jan 15, 2018 at 2:41 PM Lucas Gadani <l...@google.com> wrote:
Your numbers here look like a significant regression, so I'm guessing there must be something wrong with your testing environment.

Can you try running the benchmarks on the perf bots? Try using a  --pageset-repeat of around 200-300 for Speedometer, it'll typically run in 4-5 hours.

The other test that I usually use for innerHTML parsing is blink_perf.parser textarea-parsing (https://cs.chromium.org/chromium/src/third_party/WebKit/PerformanceTests/Parser/textarea-parsing.html), but with your change it likely won't affect it much, though it's still useful to know if it regresses.



PhistucK


Ian

To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.



--
kouhei
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.



--
/* Opera Software, Linköping, Sweden: CET (UTC+1) */

--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.

--
You received this message because you are subscribed to the Google Groups "blink-dev" group.

Yoichi Osato

unread,
Jan 15, 2018, 9:10:04 PM1/15/18
to Lucas Gadani, Rakina Zata Amni, Ian Kilpatrick, PhistucK, Daniel Bratell, Kouhei Ueno, Dave Tapuska, Daniel Vogelheim, blink-dev, TAMURA, Kent
I recommend you posting summary of result(just like "10% faster!") first and describe and/or link to detail/raw data later.

2018年1月16日(火) 4:42 Lucas Gadani <l...@chromium.org>:

Rakina Zata Amni

unread,
Jan 17, 2018, 4:15:19 AM1/17/18
to Yoichi Osato, Lucas Gadani, Ian Kilpatrick, PhistucK, Daniel Bratell, Kouhei Ueno, Dave Tapuska, Daniel Vogelheim, blink-dev, TAMURA, Kent
Sorry about the unclear data/summary! I just found out about perf bots and ran them yesterday. The command I used is: tools/perf/run_benchmark trybot --pageset-repeat=200 all-linux speedometer2. List items are in the format of [framework name] (avg slowdown or speedup in ms  / avg slowdon or speedup in percentage). Insignificance/significance is marked by the benchmark result, I'm assuming it's using average and std dev for that. I ordered the list items by percentage.

Optimizing Short (length < 100) strings vs Tip of Tree 

Total: -2.856 ms / 0.054% speedup

Insignificant slowdown on 8 frameworks:
  • Angular2-TypeScript-TodoMVC (+0.523ms / 0.478%)
  • Elm-TodoMVC (+1.656ms / 0.476%)
  • VueJS-TodoMVC (+0.234ms / 0.429%)
  • React-Redux-TodoMVC (+1.912 ms / 0.420%)
  • AngularJS-TodoMVC (+0.959ms / 0.242%)
  • BackboneJS-TodoMVC (+0.202ms / 0.168%)
  • Preact-TodoMVC (+0.056ms, 0.161%)
  • React-TodoMVC (+0.071ms / 0.030%)
Significant slowdown on 1 framework:
  • EmberJS-TodoMVC (+1.794 ms / 0.491%)
Insignificant speedup on 4 frameworks:
  • jQuery-TodoMVC(-2.834ms, 0.524%)
  • Flight-TodoMVC(-0.390ms / 0.230%)
  • EmberJS-Debug-TodoMVC (-2.826 ms / 0.205%)
  • Inferno-TodoMVC (-0.882ms / 0.125%)
Significant speedup on 3 frameworks:
  • Vanilla-ES2015-TodoMVC (-1.391ms / 0.967%)
  • Vanilla-ES2015-Babel-Webpack-TodoMVC (-1.059ms / 0.748%)
  • VanillaJS-TodoMVC (-0.881ms / 0.735%)

Complete comparison: https://00e9e64bac2df76bc4b29d576591244c39d5a6939c5b0423c9-apidata.googleusercontent.com/download/storage/v1/b/chromium-telemetry/o/html-results%2Fresults-2018-01-16_05-36-07?qk=AD5uMEuUao_mphN9tIU0JkL4eAGCKGL1lZGq1tuyhaPQ5PhmqpADNf0SOYfptohZDIdkFJ4ueHSoU6RD0C3T8o-dE97MZdtO9z0ViEJiqy7gngWVm8d92LPzK_jCivCBK422qxkverDKqBReS_6YqTJJrMPeKafr2Rwow6BPLDCJdf-oQURTJFcHZElgYgmgPm9pcwuY_CjetsUVa_nlCPnRy_vL6ZbaYRMiThP7CiXA14HxkupCsE8FI08oTsvWfQd0txfTIoDaP-tSH5MYeXxGwQSYTMos_2TpxzVyF2_boMUkoxl2y0varRNlHwGRZ4ySd0N6tgwF7wUtdIWkiyPdlyk7aLUkeiXo3ahdWaazQu1xgMfVQQgyjiwzAOZoO2omS7-tFC9Bc9RsnA280eJ_9WgkjbD7S17nk7kcWL1yg_K8cJUlZPnkpffDPdyTONAOLZG30iR40FyBFVtb1Y2yFazSqOnYrXB7ZwJd0I4ubG5EDue6FyLXLeIeGR6qEYVVQKcue2cMsK-YaDRzn47H8mS5HQXYGvoixv3FbQvzStug9BHhUoUv4e2i5ND__un_v1_8Shqs_n4R2u9Q8oelJk73q_dt6hUaJPFDdEUYdL6kRwIsRQQespFdXIA8jq-qOEl-u4iQor2M7NhGdBTtwIqpFccHUWgwYnwcxYlzAkc9lA3JwPFCsfwNuTiCcHbbNJKTVO89l2vnn2KvlSgVjmoXzkhvZ6W-A9OXZF-7v5D7UdJkB5t4w8RvCxwHp32Pn0knflhTrMQfAG920C9C2OZFJhohIQ#r=TOT&s=%25%ce%94avg


Optimizing Empty strings vs Tip of Tree

Total: -10.729ms / 0.201% speedup

Non-significant slowdown on 1 framework:
  • Flight-TodoMVC (+0.067ms / 0.040%)
Significant slowdown on 1 framework:  
  • EmberJS-Debug-TodoMVC (+5.437 ms / 0.395%)
Non-significant speedup on 9 frameworks:
  • Preact-TodoMVC (-0.295 ms / 0.838%)
  • AngularJS-TodoMVC (-1.941 ms / 0.242%)
  • BackboneJS-TodoMVC (-0.480ms / 0.396%)
  • Angular2-TypeScript-TodoMVC (-0.415ms / 0.377%)
  • VueJS-TodoMVC (- 0.205ms / 0.373%)
  • Inferno-TodoMVC (-2.452ms / 0.347%)
  • React-TodoMVC (-0.890ms / 0.194%)
  • React-Redux-TodoMVC (-0.890ms / 0.194%)
  • Elm-TodoMVC (-0.492ms / 0.141%)
  • EmberJS-TodoMVC (-0.013ms / -0.004%)
Significant speedup on 4 framework:
  • jQuery-TodoMVC (-5.398ms / 1.093%)
  • Vanilla-ES2015-Babel-Webpack-TodoMVC (-0.993ms / 0.696%)
  • Vanilla-ES2015-TodoMVC (-0.978ms / 0.676%)
  • VanillaJS-TodoMVC (-0.631ms / 0.522%)

Complete comparison: https://00e9e64bac721efbbdeca9288db1d05b446677a27b8f623bea-apidata.googleusercontent.com/download/storage/v1/b/chromium-telemetry/o/html-results%2Fresults-2018-01-16_07-30-30?qk=AD5uMEtfMJG2VIQ8CtqYd3tyESIECc7vc_byTvTyMsegi6RjTUp_h-dSqd9CHZYU8P3z_3MKhFxa7H_OS-zMALzO91uEUBruMCFJ5u56Hzhu1yxc4taAX3GMKv2e6Epzd6k-Pv9xTzKgl2VYWNCmF8VVcmKpiej7VLQaRrlJ7HzBtfFgke-f5WyfBwGaprLSH3gkU0T0i7YGNoU0inPDWrU3LM4sNhbbhr8_pDtHX-9GFBcqH1ZrOELb9JBMDu1HlpmOMHlYI_zrhqc9NlDkBZhnurk5TGNz3K5lFy9cIvDfODxOIp-J0oLDHLjGKB3knvmP3KXPTeMxwcDh6BxZPRndkcdW-_AlwCzYFB_ejFiAQ7Smt0_ib5FHtAOUSVYXBUlxc5UgPmD0pzkLwy-OZmyzuafmhSwxCP24Sh_NUuuAFA9hL4w_wdXd-Q4AFmZefJSepOs_pQvTHvbziJ6K1Tu_Gb-jeEQ2iln3e9_u13yw-PSAMa0ExmdBArS9e5xAJISSNMBp5LQ5Ov8mW2G5VsT6NBs9FqtTWnVoB3o4YijrLhNxba5pIs8Wc_ynWnp81RlHGpXPe9JLHVhbMqDBqNMz_GZNMNtojplA2L-dGIiHRCRYO2GrNFJvd2Ooydacs2koxeP0H3eW-OhRh3_MYjOE9lhjrBeDUptZN1Zm4sBl9gXQjPdryx3aYxHSv4iubs4P4WL1d97HZkzJQM0tLJgCYdv6Ue0vw_9pJT2aIohV_6jESN977lGIJV4FkmK1mqGQt8x1ZBwQlTnDE9w9ixbpdC74htq2jg#r=TOT&s=%25%CE%94avg&g=name&c=0




PhistucK


Ian

To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.



--
kouhei
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.



--
/* Opera Software, Linköping, Sweden: CET (UTC+1) */

--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.

--
You received this message because you are subscribed to the Google Groups "blink-dev" group.

--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.

Daniel Bratell

unread,
Jan 17, 2018, 10:49:08 AM1/17/18
to Yoichi Osato, Rakina Zata Amni, Lucas Gadani, Ian Kilpatrick, PhistucK, Kouhei Ueno, Dave Tapuska, Daniel Vogelheim, blink-dev, TAMURA, Kent
Small changes but what I get from those is that it is enough to special case the empty string unless the "short string" case can be made faster.

(link to full results seems to have expired but I just wanted to check the noise levels to see in what range the results might be in)

/Daniel


PhistucK


Ian

To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.



--
kouhei
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.



--
/* Opera Software, Linköping, Sweden: CET (UTC+1) */
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CACPC1r5nRLvRxSHyOkr9N4k9Q1oJTs3bEN5xxqFXcJ6uVog-1A%40mail.gmail.com.

Lucas Gadani

unread,
Jan 17, 2018, 12:00:59 PM1/17/18
to Rakina Zata Amni, Daniel Bratell, Yoichi Osato, Ian Kilpatrick, PhistucK, Kouhei Ueno, Dave Tapuska, Daniel Vogelheim, blink-dev, TAMURA, Kent
I believe the links for the tryjob run are https://ci.chromium.org/buildbot/tryserver.chromium.perf/linux_perf_bisect/7919 and https://ci.chromium.org/buildbot/tryserver.chromium.perf/linux_perf_bisect/7920 where you can see the results.

Overall, I think your change looks like a good improvement. Based on these numbers, it seems that the empty string optimization performs better than the <100 length strings. My suggestion is go ahead and land the optimization for empty strings, and try to gather more data to determine if the <100 strings are worth optimizing for.

Rakina Zata Amni

unread,
Jan 17, 2018, 9:11:18 PM1/17/18
to Lucas Gadani, Daniel Bratell, Yoichi Osato, Ian Kilpatrick, PhistucK, Kouhei Ueno, Dave Tapuska, Daniel Vogelheim, blink-dev, TAMURA, Kent
Whoops, sorry again. The tryjob runs linked by Lucas is correct, if anybody wants to see the data.
Alright, it seems like it's best to have the empty string optimization only for now. I'll try to find a way to gather data round the short string optimization. Thanks for all the replies! :)



PhistucK


Ian

To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.



--
kouhei
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.



--
/* Opera Software, Linköping, Sweden: CET (UTC+1) */
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.
--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+unsubscribe@chromium.org.
Reply all
Reply to author
Forward
0 new messages