Intent to implement lazy-block layout

1,165 views
Skip to first unread message

Elliott Sprehn

unread,
Apr 22, 2013, 7:18:27 PM4/22/13
to blink-dev, Ojan Vafai, Tab Atkins, Levi Weintraub
Primary eng (and PM) emails
esp...@chromium.org, le...@chromium.org, oj...@chromium.org

Spec

Note this feature is currently in the experimental phase and we need more implementation experience to understand the shape of the API before writing the spec. We plan to build it behind a flag.

Summary
The proposed feature allows Blink to only go through layout for elements that are inside the viewport to greatly reduce page load times and the time spent adding dynamic content. Developers can page in new content while the user is scrolling without fear of making the app slow as well.

Motivation
Developers do all kinds of crazy things to implement infinite scroll and often make their pages janky and slow by loading content while the user is scrolling. This proposal makes appendChild() and innerHTML significantly faster if the content is not inside the viewport and makes loading the initial page much faster.

ex. Our demo has a 4 second layout that's reduced to 32ms with lazy-block.

Compatibility Risk
None. This is a totally new feature and is just experimental right now.

OWP launch tracking bug?
None, this will be behind a flag. We'll file a bug when we know what the shape of the API is.

Row on feature dashboard?
Yes.

Requesting simultaneous permission to ship?
No.

- E

Stephen Chenney

unread,
Apr 22, 2013, 7:40:40 PM4/22/13
to Elliott Sprehn, blink-dev, Ojan Vafai, Tab Atkins, Levi Weintraub, graphi...@chromium.org
The left hand doesn't know what the right hand is doing.

In the recent impl-side painting talk, it was pointed out that we rasterize content outside the viewport in accordance with the expected scroll direction. If you only do layout for the viewport then they will be painting the wrong thing in anticipation of the scroll.

Everyone get together now and figure this out.

I also wonder about SVG reference links that go to other parts of the page and require them to be laid out for correct rendering of visible content.

Stephen.

Ojan Vafai

unread,
Apr 22, 2013, 7:50:54 PM4/22/13
to Stephen Chenney, Elliott Sprehn, blink-dev, Tab Atkins, Levi Weintraub, graphi...@chromium.org
On Mon, Apr 22, 2013 at 4:40 PM, Stephen Chenney <sche...@chromium.org> wrote:
The left hand doesn't know what the right hand is doing.

In the recent impl-side painting talk, it was pointed out that we rasterize content outside the viewport in accordance with the expected scroll direction. If you only do layout for the viewport then they will be painting the wrong thing in anticipation of the scroll.

The email didn't go into technical detail. The plan is to layout everything the compositor thread needs, including the extra buffer space. The prototype we put together already does this FWIW.
 
Everyone get together now and figure this out.

I also wonder about SVG reference links that go to other parts of the page and require them to be laid out for correct rendering of visible content.

There are exactly the sorts of issues we want to figure out that are hard to identify without just building it (behind a runtime flag of course). Most likely, I think we would just not support these, i.e. SVG references to things inside a lazy-block just won't work. Alternately, we could make it work and have this force a layout of elements not in the viewport if we think the use-cases are compelling. Right now, we're still at the point of trying to figure out much bigger design issues (e.g. can we avoid style recalc for off-screen elements).

Stephen Chenney

unread,
Apr 22, 2013, 8:08:51 PM4/22/13
to Ojan Vafai, Elliott Sprehn, blink-dev, Tab Atkins, Levi Weintraub, graphi...@chromium.org
I kindly suggest the one-sentence feature description be "The proposed feature allows Blink to only go through layout for regions that are requested by the compositor to greatly reduce page load times and the time spent adding dynamic content.".

I might be embarrassing myself here, but for SVG I want something like this:
1. Maintain a Document-level dependency graph for SVG content. Dependencies are implied by parent-child DOM relationships, plus resources (filters, masks, paints, text paths, etc)
2. You can have bounding regions for each node in this graph, so you will be able to figure out what to lazily layout
3. Layout needed regions in topological order.

I think, given the way SVG sizing works, that this will generate the right result. We really shouldn't be laying out SVG the same way we lay out HTML because the way sizes are computed is almost exactly opposing.

I am glossing over places where there are percentage widths, which may cause all this to fall apart.

This also will address a whole series of bugs we have with SVG causing out-of-order layout of other nodes that ultimately never get laid out. It is also the layout model needed for MathML, as I understand it.

Stephen.

Philip Rogers

unread,
Apr 22, 2013, 11:17:26 PM4/22/13
to Stephen Chenney, Ojan Vafai, Elliott Sprehn, blink-dev, Tab Atkins, Levi Weintraub, graphi...@chromium.org
I'm not aware of any optimizations to layout specifically for the slightly different UX of scrolling on tablets and mobile devices. Have you considered these for lazy layout?

For example, the scrollbar feels pretty useless on a tablet device on an infinite scroll page. If you got rid of it, could lazy layout be even lazier?

Philip

Levi Weintraub

unread,
Apr 23, 2013, 1:02:01 PM4/23/13
to Philip Rogers, Stephen Chenney, Ojan Vafai, Elliott Sprehn, blink-dev, Tab Atkins, graphi...@chromium.org
Philip: We're starting with an approach that should work and be a performance improvement on all platforms. We'll look into further optimizations once we have a solid working version.

Stephen: Your one-line description sounds good. As for your statement about performing SVG layout differently than HTML, this seems orthogonal to our proposal. As Ojan said, SVG references to contents inside a Lazy Block we'll likely not support, and we're placing constraints on the contents of lazy blocks that sound similar to what you're stating in your list. Perhaps it makes sense to chat in person to try and get on the same page.

Eric Seidel

unread,
Apr 23, 2013, 5:29:54 PM4/23/13
to blin...@chromium.org, Ojan Vafai, Tab Atkins, Levi Weintraub
I strongly support this work.

It is very important to me that optimizations discovered as part of this work are also applied to the common cases w/o authors needing to opt-in to lazy layout behavior.  I believe the real win is for the 99% of sites which will never opt-in to this API, but will go down faster, optimized paths which may result from this work.

In a perfect world, we would not need/want to do experimental work like this on trunk, but rather in a branch.  Part of me would like to push this to GitHub or git.chromium.org, but neither of those seem practical given our current tools.

LGTM to implement.

Philip Rogers

unread,
Apr 23, 2013, 5:55:32 PM4/23/13
to Eric Seidel, blink-dev, Ojan Vafai, Tab Atkins, Levi Weintraub
I do not think we're going down a good path by landing this behind a flag.

The important parts of the lazy block layout algorithm can be implemented in JavaScript today. A JavaScript implementation will be testable in other browsers and will have a better chance of resulting in an API that meets the performance needs of other browsers too.

I'm seriously excited about the work being proposed here but I think it needs more discussion with other vendors before experimenting in trunk.

Philip

Tom Wiltzius

unread,
Apr 25, 2013, 1:33:31 PM4/25/13
to Philip Rogers, Eric Seidel, blink-dev, Ojan Vafai, Tab Atkins, Levi Weintraub
On Tue, Apr 23, 2013 at 5:55 PM, Philip Rogers <p...@google.com> wrote:
I do not think we're going down a good path by landing this behind a flag.

The important parts of the lazy block layout algorithm can be implemented in JavaScript today. A JavaScript implementation will be testable in other browsers and will have a better chance of resulting in an API that meets the performance needs of other browsers too.

Which parts do you think are implementable in JS today? Specifically, do you have a recommended approach for appending not-yet-visible content to a very long list of some kind that won't trigger relayout at the time of append?

Philip Rogers

unread,
Apr 25, 2013, 2:16:13 PM4/25/13
to Tom Wiltzius, Eric Seidel, blink-dev, Ojan Vafai, Tab Atkins, Levi Weintraub
Lazily attaching nodes is one approach to appending nodes without triggering layout. This is being used by infinite scroll sites today.

Ideally, this work would be done on a public branch but our current infrastructure doesn't allow for that yet. Implementing this behind a flag may be the best option.

Tom Wiltzius

unread,
Apr 25, 2013, 2:32:28 PM4/25/13
to Philip Rogers, Eric Seidel, blink-dev, Ojan Vafai, Tab Atkins, Levi Weintraub
On Thu, Apr 25, 2013 at 2:16 PM, Philip Rogers <p...@google.com> wrote:
Lazily attaching nodes is one approach to appending nodes without triggering layout. This is being used by infinite scroll sites today.

But isn't this exactly one of the the problem cases that lazy block layout is trying to address? I.e. that today you can lazily append nodes, but whenever you do you're going to trigger relayout, likely of the whole list, and with it jank the scroll that's supposed to be infinite (and infinitely smooth)? I have not seen sites lazily appending nodes in this manner today but avoiding a jank when adding content.

With lazy layout working hand-in-hand with the compositor, my hope would be that you'd be able to lazily append nodes far below the fold of the screen, which would be very fast because they don't require any layout at the time (and don't cause any invalidations). The layout would later occur as needed based on the scroll position (i.e. when the compositor asked for it), and incrementally, allowing continued smooth scrolling. 

This was my read of "reducing... time spent adding dynamic content" in "The proposed feature allows Blink to only go through layout for regions that are requested by the compositor to greatly reduce page load times and the time spent adding dynamic content." Am I getting it wrong?

Philip Rogers

unread,
Apr 25, 2013, 3:37:26 PM4/25/13
to Tom Wiltzius, Eric Seidel, blink-dev, Ojan Vafai, Tab Atkins, Levi Weintraub
Tom,

Our layout is already teched up to that level. If you have 5000 block elements and append one more, the first 5000 are not laid out again.

The proposal at hand is about not doing unviewable layout, i.e., skipping the layout of nodes below the fold. Facebook.com does this, albeit poorly: if you keep scrolling they will keep appending new posts without doing a full page relayout.

There may be compositor wins here but they haven't been described yet.

Philip

Philip Rogers

unread,
Apr 25, 2013, 5:02:31 PM4/25/13
to Tom Wiltzius, Eric Seidel, blink-dev, Ojan Vafai, Tab Atkins, Levi Weintraub
Tom,

I put together an example showing this lazyjs approach for squished presidents: http://philbit.com/lazyjs/lazyjs.html

James Robinson

unread,
Apr 25, 2013, 6:10:38 PM4/25/13
to Philip Rogers, Tom Wiltzius, Eric Seidel, blink-dev, Ojan Vafai, Tab Atkins, Levi Weintraub
The problem is here:

function updateViewport() {
...
var firstVisibleItem = Math.floor(scrollTop / itemHeight);
var lastVisibleItem = Math.ceil((scrollTop + clientHeight) / itemHeight);
...
}

This is trying to do a visibility determination from JavaScript, but you can't actually do that accurately without knowing what the compositor needs to have prerendered.  The notion of the 'important' part of the viewport is something that requires integration with the compositor in C++ to get right.

- James

Elliott Sprehn

unread,
Apr 25, 2013, 6:58:50 PM4/25/13
to Philip Rogers, Tom Wiltzius, Eric Seidel, blink-dev, Ojan Vafai, Tab Atkins, Levi Weintraub
On Thu, Apr 25, 2013 at 2:02 PM, Philip Rogers <p...@google.com> wrote:
Tom,

I put together an example showing this lazyjs approach for squished presidents: http://philbit.com/lazyjs/lazyjs.html



That isn't equivalent though, you're making everything display: none you think is outside the viewport so you end up with a scrollbar that's "collapsed" and you can't do "End" on your keyboard to go to the bottom or click to a specific location to jump down, find in page, make selections etc. If you grab the scrollbar and pull down you'll also hit the bottom of the track and you can't drag anymore.

The best JS demos of this I've seen need to keep spacers at the top and bottom (ex. margins) and as you scroll they recycle the DOM nodes swapping them in and out. That still breaks find in page and other stuff but otherwise works pretty well until you start threaded scrolling where you can trivially get ahead of it and see background color.

Indeed there's lots more things to think about though, both in making ours faster and getting all the use cases pinned down.

- E

Nat Duca

unread,
Apr 26, 2013, 3:23:12 PM4/26/13
to Elliott Sprehn, Philip Rogers, Tom Wiltzius, Eric Seidel, blink-dev, Ojan Vafai, Tab Atkins, Levi Weintraub
Stepping back, one thing that I actually think we *all* agree on is we need element-level rAF. If it existed, we could use it for all sorts of things --- esprehn/leviw style lazy layout, fetching images lazily when they are <img delay>, and of course js-based stuff like pdr suggests.

Tom Wiltzius

unread,
Apr 29, 2013, 1:31:02 AM4/29/13
to Nat Duca, Elliott Sprehn, Philip Rogers, Tom Wiltzius, Eric Seidel, blink-dev, Ojan Vafai, Tab Atkins, Levi Weintraub
Perhaps this is where part of my confusion stemmed from. I was thinking more about the adding dynamic content case (infinite scroll), not viewporting (or trying to do your own viewporting in JS).

Elliott (or anyone), can you clarify what the use case / specific supporting improvements for adding dynamic content are? (again, I'm somewhat minimally going on what I otherwise know about this project plus the note in the intro that "The proposed feature allows Blink ... to greatly reduce page load times and the time spent adding dynamic content"). I'm not just trying to belabor the point -- I think this informs the scope of the work, which might be of general interest.

 
 

- E

ninjain...@gmail.com

unread,
Dec 3, 2013, 8:44:52 PM12/3/13
to blin...@chromium.org, Nat Duca, Elliott Sprehn, Philip Rogers, Tom Wiltzius, Eric Seidel, Ojan Vafai, Tab Atkins, Levi Weintraub
As far as I can tell, it sounds like the intended use case was to allow viewporting (as per the row on chromestatus.com). A great use case of this is showing large lists of content without inflating the size of the DOM. Things like slickgrid accomplish this by only showing the visible content to the user rather than every possible row. At Grooveshark, we actually had to create our own solution that involves adding a buffer of visible items below/above plus the visible content and simply recycles the DOM nodes while scrolling. Unfortunately, even with tons of micro-optimizations and terse layouts we miss rAF frequently.

Is there any movement on this feature at all? This is definitely something that has been on my radar since I heard about it from Google I/O.

Ojan Vafai

unread,
Dec 3, 2013, 8:54:14 PM12/3/13
to ninjain...@gmail.com, blink-dev, Nat Duca, Elliott Sprehn, Philip Rogers, Tom Wiltzius, Eric Seidel, Tab Atkins, Levi Weintraub
We've changed focus somewhat to <http://dev.w3.org/csswg/css-containment/>, which should give similar benefits of being able to avoid style recalc and layout of offscreen elements. That said, we're currently just in the spec-phase of this work and are not likely to getting to implementing this in the next few months.

Andrey Lushnikov

unread,
May 13, 2014, 10:22:18 AM5/13/14
to Ojan Vafai, ninjain...@gmail.com, blink-dev, Nat Duca, Elliott Sprehn, Philip Rogers, Tom Wiltzius, Eric Seidel, Tab Atkins, Levi Weintraub
Any updates on this?


To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.

Ojan Vafai

unread,
Jul 8, 2014, 10:31:40 PM7/8/14
to Andrey Lushnikov, Mark Caudill, blink-dev, Nat Duca, Elliott Sprehn, Philip Rogers, Tom Wiltzius, Eric Seidel, Tab Atkins, Levi Weintraub
Theoretically, we still intend to pursue this, but it's not actively being worked on. When we took a closer look at performance, we found a lot of low-hanging fruit that we could fix without exposing new APIs, so we're focused first on that and we've made a lot of good progress in the past few months. We'll probably get back to this one day, but for now we're more focused on making sure that basic non-infinite use cases can consistently hit 60fps on low-ish-end hardware. There's still a lot of work to do before this is the biggest issue.
Reply all
Reply to author
Forward
0 new messages