Slowdown in Firefox due to re-styling

Currently we have a page loading around 70 separate instances of codemirror (that’s an entirely different UI/UX problem). In Chrome, each instance takes about 20 ms to load and the entire page loads in a reasonable amount of time. In Firefox (58.0.2 64-bit), each instance takes between 1000-2000 ms (1-2 seconds), so the page takes between 1-2 minutes to load (naively).

Profiling in Firefox shows a significant amount of time and resources are spent in the middle of each CodeMirror.fromTextArea() call re-styling and re-flowing the HTML, specifically multiple native FF calls to Recalculate Style, Apply Style Changes and Layout. Usually these take only a few ms, but the Layout call triggers 10 times or so, taking 100-200 ms each call. The page is designed for modern browsers, ES2105 or so, using primarily Flex display. Removing the page’s CSS entirely causes the page to load in less than a second, reducing the codemirror calls to an inconsequential amount of time again.

As an example, one call to CodeMirror.fromTextArea() will trigger Layout with the following Stack:
Duration: 114.19 ms
--- updateGutterSpace codemirror.js:4325
--- updateGutters codemirror.js:4350
--- CodeMirror codemirror.js:760
--- CodeMirror codemirror.js:7746
--- fromTextArea codemirror.js:9546
custom.js:24971
--- i jquery-1.12.4.min.js:3
--- fireWith jquery-1.12.4.min.js:3
--- ready jquery-1.12.4.min.js:3
--- K jquery-1.12.4.min.js:4325

Followed by a few Recalculate Style, Apply Style Changes and identical Layout calls (however the subsequent identical Layout calls are all < .03 ms). This is all followed by (e.g.) Layout Stack:
Duration: 108.26ms
--- textHeight codemirror.js:2949
--- estimateHeight codemirror.js:2993
--- estimateLineHeights codemirror.js:3011
--- attachDoc codemirror.js:4706
--- CodeMirror codemirror.js:7793
--- CodeMirror codemirror.js:7746
--- fromTextArea codemirror.js:9546
custom.js:24971
--- i jquery-1.12.4.min.js:3
--- fireWith jquery-1.12.4.min.js:3
--- ready jquery-1.12.4.min.js:3
--- K jquery-1.12.4.min.js:4325

This process continues to repeat, with slightly differing Layout calls.

Try initializing the first CodeMirror, and then calling operation on it and initializing all the others from the body of the function you pass. That should synchronize the layouts, speeding things up a lot.

1 Like

Thank you for the response. For some reason it went to my spam folder so I almost missed it.

Anyway, I was able to test in our situation, this technique reduces each instantiation call time by about 1/2 to 1/3 (typically down to about 600 ms per call), which still ends up being about 30 seconds if done all at once. However it also delays UI updates while running, so chunking the calls doesn’t seem to work as FF will go back and forth from being completely unresponsive (while UI updates) to not showing anything (while the code runs).

I think this technique would work if we weren’t already so far out of range, and we’ll still need to fix the fact that we’re trying to load 70 instances at once to get this working in an ideal manner. The only reason I think it’s worth looking into at all is because e.g. Chrome has no problems with this at all.