by Warren Gaebel | Oct 30, 2012
When a change to the render tree represents a new appearance (e.g., a new image), but not a new position or size, the rendering engine kicks in and repaints the corresponding rectangle on the end-user’s screen. Since this does not change the frame’s position or size, it does not affect any other frame in the render tree. However, it does chew up CPU cycles and the changing graphic can distract the end-user.
Performance Consideration:
Avoid repaints as much as you can. Repaints will degrade performance, but not nearly as much as reflows (described in the next section).
Terminology Note: Painting and drawing are the same thing. The “re” in repaint and redraw merely indicates that it’s the second or subsequent occurrence.
Did you check out gyuque’s visualizations in the last episode? Did you notice all the repetition? Well, here’s the cause: Reflows often trigger other reflows. This is very different from a repaint. A repaint does not trigger repaints of other frames, but a reflow can trigger many, many more reflows.
Performance Consideration:
The previous episode told us never to use the DOM during page load. However, after the page is completely loaded, it’s a different story. At this point, dynamic web pages can’t be dynamic if you don’t use the DOM tree. And we do want dynamic web pages, right? However, we need to realize that our use of the DOM tree can be responsible for performance problems, and we need to adopt certain programming practices to minimize those problems. Some of those practices follow.
Performance Consideration:
Because reflows are such a huge performance issue, avoid anything that triggers one (as much as possible):
This tip applies to event-driven scripts, scripts that execute after onLoad, scripts that execute after a timer expires, and scripts that execute while the page is loading.
Performance Consideration:
To change a node’s formatting, clone the node, change the formatting in the cloned copy, then put the cloned copy into the content tree in place of the original node. This technique will cause one reflow; working directly on the original node can cause one reflow for every formatting change. And don’t forget about all the other reflows on all the other elements that are affected.
Performance Consideration:
Another much-touted technique is to change the display attribute of the target node to none, make the formatting changes, then change the display attribute back to its original value. This accomplishes the same objective as the previous tip, but it causes two reflows instead of one. Use the previous technique instead.
Performance Consideration:
Changing the position or size of elements that use static or relative positioning causes other elements to be reflowed. Changing the position or size of elements that use absolute or fixed positioning doesn’t. Use absolute positioning as much as possible. You may want to consider fixed positioning for navbars, headers, footers, ads, etc.
Performance Consideration:
HTMLCollection objects contain live nodes. Every time the script touches nodes in the HTMLCollection object, it is actually touching the content tree. When using HTMLCollection objects, deep clone them and work with the cloned copies. [When finished working with an element in the cloned collection, remember to put it back into the live tree or the changes won’t appear in the browser.]
Performance Consideration:
Avoid universal, multiclass, and pseudo selectors in CSS. Never use CSS expressions.
Performance Consideration:
Avoid layout changes near the top of the document. If the change is near the bottom of the document, it probably has to reflow the few things below it, but what’s above is likely to remain the same.
Terminology Note: Layout and flow are the same thing. The “re” in reflow and relayout merely indicates that it’s the second or subsequent occurrence.
Event handlers can be attached to elements to listen for events. The data structures that keep track of this are also stored in the DOM. However, an under-the-covers performance issue rears its ugly head when we use too many event handlers. Apparently, the number of event handlers doesn’t scale well.
Performance Consideration:
This becomes a non-issue if we have only one handler per event type for the entire page. This magic event handler kicks in every time the specified event occurs on any element in the page, then it checks to see which element is the target of the event. It then executes the appropriate code for that event type on that target. Here are the key lines of code to make this happen for onclick events (adapted from page 58 of Zakas’ book):
document.onclick = function(e) { e = e || window.event; var target = e.target || e.srcElement; switch (target.nodeName) { case "A": return handleAonclick(e); case "B": return handleBonclick(e); case "C": return handleConclick(e); case "D": return handleDonclick(e); default: return true; } }
The following are listed alphabetically, but, coincidentally, also in the order I would recommend reading them.
Gaebel, Warren. Page Rendering & Reflow Performance. Published 2012.04.13 at /2012/04/page-rendering-reflow-performance/. Links to a few other articles and a short list of their performance tips.
Stefanov, Stoyan. Rendering: Repaint, Reflow/Relayout, Restyle. Published 2009.12.17 at https://www.phpied.com/rendering-repaint-reflowrelayout-restyle/. I find Stoyan’s articles useful almost every time. This article helped me understand the rendering process some time ago, and I’m sure it can help others, too.
Zakas, Nicholas C. “Repaints and Reflows” in High Performance JavaScript. Published March 2010 by O’Reilly Media and Yahoo Press; ISBN 978-0-596-80279-0. This section of the book is available as a preview at Google Books. It explains the DOM/CSS reasoning behind some of the above performance tips.
Category: Website Performance | Tagged No Comments.