Slowdown in Firefox due to re-styling


#1

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.


#2

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.