This is a continuation of Tony's thread, focused on Layout.
I'm sending this to blink-dev instead of just the Google Blink-layout
folks in case others are interested.
I profiled [3] 5 of the top 10 sites listed as "slowest layout" in
Tony's top 10k:
https://docs.google.com/a/chromium.org/document/d/1ca_Q7xePmCRqaYnHe7vkpCmKNFNLdDXvzgtUPt9iG8w/edit#
They all have a very long delay (unclear entirely why) until they send onload.
During that time, they do a zillion layouts. [4]
I believe most of these layouts are caused by marquee/animation emulation:
http://icon.55bbs.com/homepage/js/index20120411_ys.js?v=1.5 see
rollText.run [1]
http://img1.cache.netease.com/cnews/js/ntes_ui/ntes_ui_slide_0.3.0_min.js
see _setPos [2]
Many of these layouts only layout the few elements invalidated.
But others do a full FrameView::layout(). (I'm not yet sure why?
Maybe the layout timer?)
When we do a FrameView::layout() that's when we get in trouble. We
get in trouble for 2 reasons:
1. We're calling updateCompositingLayersAfterLayout, which causes
eager compositing layer updates (even if the compositor may not need
them yet).
2. We're calling updateLayerPositionsAfterLayout, which unfortunately
uses clippedOverflowRectForRepaint to recursively walk up the
rendering tree. During layout() clippedOverflowRectForRepaint uses
layoutState() to quickly compute the value, but
updateLayerPositionsAfterLayout happens after layout() is done, and
doesn't get to use the layoutState() cache.
There is a 3rd bug implied from the above... why the heck are we doing
full FrameView::layout() calls in the first place? I believe that may
be the deferedLayoutTimer in action. Elliot/James have mentioned
before that we should only ever be doing compositor or JS-driven
layouts. It's not clear what is driving these full-page layouts, the
Inspector doesn't tell me.
I'm interested in your thoughts and feedback.
-eric
1. run: function(id, delay) {
var oLiFirst = this.liArr[id][0];
var liMarTop = oLiFirst.style.marginTop;
var liTopNum = parseInt(liMarTop);
var c = Math.abs(liTopNum);
if (c < parseInt(this.oUlH[id])) {
c++;
oLiFirst.style.marginTop = "-" + c + "px"
} else {
if (Math.abs(liTopNum) == parseInt(this.oUlH[id])) {
clearInterval(this.go[id]);
this.oParentUl[id].removeChild(oLiFirst);
this.oParentUl[id].appendChild(oLiFirst);
this.liArr[id][this.liArr[id].length -
1].style.marginTop = "0px";
this.timeout[id] = setTimeout(function(obj, id,
childtags, delay) {
return function() {
obj.start(id, childtags, delay)
}
}(this, id, this.childNode[id], delay), delay)
}
}
}
2. _setPos: function(e) {
var t = this;
t._bPos = e;
t._body.style.left = -t._bPos + "px";
if (t._handle) {
t._hPos = t.bhRate ? e / t.bhRate : 0;
t._handle.addCss(t._fix.pos + ":" + t._hPos + "px")
}
}
3. Profiling instructions, care of Tony:
https://docs.google.com/a/chromium.org/document/d/1_Zh6mLgGOhH_ccnahn-gTVD91xazQ4sG8asDbEgaSpY/edit
4.
https://code.google.com/p/chromium/issues/detail?id=261439