Severe performance penalty when nesting flex containers




4 years ago
3 years ago


(Reporter: heavy, Unassigned)



Firefox Tracking Flags

(Not tracked)



(1 attachment)

4.86 KB, text/html


4 years ago
Created attachment 8504953 [details]

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.1.17 (KHTML, like Gecko) Version/7.1 Safari/537.85.10

Steps to reproduce:

I am noticing a severe performance slow down when using nested flex containers. It is possible that I am abusing display flex, but it gives me the capabilities I need in a fairly concise way. A little background…

I am using flex containers to create a flexible/responsive layout mechanism for constructing a web page out of widgets. In short, a page is composed of 1 to R rows, where each row is a row-wise flex container. Each row can have 1 to C columns, where each column is a column-wise flex container. Lastly, each column can have 1 to B blocks, where each block is also a flex container. It is possible that I could avoid using a flex container in some cases, but I am typically using the flex container to stretch content that might otherwise be too small or not consistently sized.

Summarizing the general layout behavior I am trying to achieve, the "row" flex container ensures that all contained columns are consistently sized as tall as the tallest column on a given wrap line. The "column" flex container stretches its last block if it wouldn’t otherwise consume all remaining height of the column. The "block" flex container stretches its contained widget (which is not shown in this example) to fill its containing block, which may have been stretched if it was the last block in a column. One last point, this structure can nest (i.e., a block may ultimately contain a nested row and its associated structure).

This is an approximation of my real web app, but the important thing to note is that inserting nested layouts is actually inserting 3 flex containers at a time, so the attached HTML file has 6 nested levels of the described layout structure, resulting in 18 nested flex containers.

Actual results:

At six layout levels, it is pretty much unusable, if you add one more nested layout level then it is definitely unusable. In my real app, the nesting of layout levels is not actually so deep normally, but the actual structure is more complex and introduces a couple more flex containers so the effect is the same at lower levels of layout nesting.

(Results vary based on the speed of the machine, so feel free to add extra levels since the fall off is pretty quick. I am testing on an older iMac.)

Expected results:

It shouldn't be so slow.

The provided example is quick in Safari and even in our live web app which is a dynamically generated, JavaScript-infested complicated version of a similar scenario. :-)

Comment 1

4 years ago
Somehow related to bug 946167 and bug 991517.

Comment 2

4 years ago
Further note, Safari eventually starts to slow down too, but Chrome appears to continue to handle it fairly well up to 26 layout levels (i.e., 84 nested flex containers) before I got bored.
Thanks for the testcase. This takes ~3s to load in Nightly on my desktop work machine, and it takes ~20s if I uncomment the innermost chunk ("Nested layout 7").

And Chrome does indeed load it near-instantaneously.

It's possible that bug 1054010 will fix this; tentatively marking as dependency.
Depends on: 1054010
Ever confirmed: true
OS: Mac OS X → All
Hardware: x86 → All
Version: 36 Branch → Trunk

Comment 4

4 years ago
Just to correct my math, I tested Chrome up to 26 layout levels, which is 78 nested flex containers, not 84.
Flags: needinfo?(dholbert)
Blocks: 1097482


4 years ago
Blocks: 1108772

Comment 5

4 years ago
I'm pretty sure the issue being highlighted here is the same one I'm seeing in bug 1108772. For what it's worth, the test case attached to my bug allows for some user interaction (dragging the top banner and vertically resizing the nested divs). I mention this because the issue is not simply that the page takes a long time to load/render--it's also that you can't really use it even after it has been drawn.

In my test case there's a line declaring a variable named "depth" that's currently set to 11. I set this to over 300 in Chrome and it was still completely usable after loading instantly. Firefox was about dead (not responding) at a depth of 20.

Comment 6

4 years ago
Just a quick note for anyone still following this bug: you may be able to render the layout you want using the old 2009 -moz prefixed syntax. The comments and attachments in bug 1108772 outline this approach.
Sorry for the delay here.

Good news -- I've verified that my local patches for bug 1054010 (and its dependencies) do indeed fix this (as I suspected in comment 3). They make the attached testcase load near-instantaneously, in a debug build, even with the inner section uncommented.  In contrast, this takes several minutes to load in an un-patched debug build.

I need to rework the patches a bit before they're ready for review/landing, but with any luck, I should have that bug (and its helpers/dependencies) fixed on trunk very soon now.

So, I'm going to mark this as a duplicate of bug 1054010.
Last Resolved: 4 years ago
Flags: needinfo?(dholbert)
Resolution: --- → DUPLICATE
Duplicate of bug: 1054010
No longer blocks: 1097482
No longer blocks: 1108772
FWIW, I just landed a fix for bug 1054010, so this should be fixed in Nightly builds in the next few days.

The regression-test that I included with that fix was based on the testcase in this bug here -- thanks for posting it!  The particular nesting-pattern seems to be very good at making this bug painful & hanging the (unpatched) browser, with a relatively small amount of content, which makes for a great regression test.

Comment 9

3 years ago
Cool. I'm glad it made a difference.
You need to log in before you can comment on or make changes to this bug.