Lessons in JavaScript Performance Optimization

Fellow Ajaxian, Michael Mahemoff, has written about an experience with optimizing JavaScript from a 90 second benchmark to 3 seconds. The hog that slowed down the system was $$(".classname") being used on a large DOM:
After some sophisticated profiling ((new Date()).getTime():D), the main culprit was revealed to be prototype's $$. It's a fantastic function, but if you try to grab all elements belonging to a certain class, and the DOM is really big, $$(".cssClassName") can be slow. *REALLY SLOW* in IE. Remedy
  • Removed trivial usages of $$() - e.g. in one case, the script was using it as a simple shorthand for a couple of DOM elements, and it was easy enough to hardcode the array. i.e. $$(".instruction") becomes [$("initialInstruction"), $("finalInstruction")]. The former notation is cuter, but unfortunately impractical on a large web page.
  • Introduced the unofficial selector addon. Seems to have improved performance in more complex queries, i.e. $("#knownId .message"), but doesn't seem to have affected performance of $$(".classname").
  • Finally, I bit the bullet and scrapped $$(".classname") altogether. It's more work, but the script now maintains the list of elements manually. Whenever an element is added or removed, the array must be adjusted. Furthermore, even the initialisation avoids using $$(), thanks to some server-side generated JS that explicitly declares the initial list of elements belonging to the class (i.e. the list that would normally be returned by $$()). To do this, the following function is called from onload(), generated with RHTML.
function findAllItems() { <% js_array = @items.map { |item| "document.getElementById('item#{item.id}'),"}.join js_array = js_array[0..-2] if @items.length>0 # Drop extra comma at end -%> return [<%= js_array %>]; }
Read more from Michael on the subject

Lessons in JavaScript Performance Optimization

Fellow Ajaxian, Michael Mahemoff, has written about an experience with optimizing JavaScript from a 90 second benchmark to 3 seconds.

The hog that slowed down the system was $$(".classname") being used on a large DOM:

After some sophisticated profiling ((new Date()).getTime():D), the main culprit was revealed to be prototype's $$. It's a fantastic function, but if you try to grab all elements belonging to a certain class, and the DOM is really big, $$(".cssClassName") can be slow. *REALLY SLOW* in IE. Remedy

  • Removed trivial usages of $$() - e.g. in one case, the script was using it as a simple shorthand for a couple of DOM elements, and it was easy enough to hardcode the array. i.e.
    $$(".instruction") becomes [$("initialInstruction"), $("finalInstruction")]. The former notation is cuter, but unfortunately impractical on a large web page.
  • Introduced the unofficial selector addon. Seems to have improved performance in more complex queries, i.e. $("#knownId .message"), but doesn't seem to have affected performance of $$(".classname").
  • Finally, I bit the bullet and scrapped $$(".classname") altogether. It's more work, but the script now maintains the list of elements manually. Whenever an element is added or removed, the array must be adjusted. Furthermore, even the initialisation avoids using $$(), thanks to some server-side generated JS that explicitly declares the initial list of elements belonging to the class (i.e. the list that would normally be returned by $$()). To do this, the following function is called from onload(), generated with RHTML.
function findAllItems() {
<% js_array = @items.map { |item| "document.getElementById('item#{item.id}'),"}.join
      js_array = js_array[0..-2] if @items.length>0 # Drop extra comma at end -%>
      return [<%= js_array %>];
}
 

Read more from Michael on the subject


September 27th, 2006

Tagged View

Tags Similar

Posts Fresh +

Categories View