Prototype and speed

Since Mike doesn’t really blog anymore, I figured I would steal his thunder and discuss some of his findings the past week.

For those of you that haven’t used Prototype before, it is a Javascript library which we use fairly heavily at webmail.  It has served us well for a while now …..

But version 1.5 is becoming too slow to be used in webmail. Being a very large web application, we don’t always have the luxury of elegant code, especially in javascript. Sometimes, we just have to do what works fastest and looks the ugliest. This past week Mike made some interesting findings, singling out some of the major performance culprits in Prototype.

Enumerable.each()

We have known this function is slow and have tried to avoid using it, but Prototype itself uses it on some very common functions such as:

  • Element.addClassName()
  • Element.removeClassName()
  • Enumerable.* (Basically all of them use each() somewhere)

Mike overrode the first two functions to use a regular loop instead of each() and saw a 200ms login improvement! That is a pretty large improvement, nearly 14% of the total javascript rendering time on login.

Element.update()

For a long time, I thought Element.update() just abstracted element.innerHTML. I was wrong. It calls stripScripts() and evalScripts(). Since we never pass in text containing script tags, we overwrote this function to just use element.innerHTML. Again, another huge performance enhancement.

Unnecessary abstractions

Prototype has added some great functionality to javascript, but sometimes they take it a little too far with their abstractions. Some functions serve very little purpose other than to add an extra function call.

  • Element.update() - Since we have taken out the stripScripts()/evalScripts(), there is really no reason to use this function
  • Element.setStyle() - As long as you don’t set opacity or float styles, don’t use this function.
  • Element.addClassName() - If you know an element doesn’t have the class name already, just call element.className += ' foobar'.