The most common use cases of Javascript require no optimization at all. However when you go about building substantial applications in javascript you will hit some walls rather rapidly. Fortunately the code you are currently writing can probably be accelerated substantially.
Step 0: Analyzing performance
Prior to attempting any tweaks, be sure to get firebug and use their console.profile() and console.profileEnd(). Test results will vary substantially during subsequent tests, but they serve their purpose for finding the bottlenecks.
Step 1: Remove Double Dollar $$ and event binding
There are many small performance differences, but several things are likely to really kill performance. One of the most nasty ones is using prototype’s double dollar $$ function (or the similar Element.select). You can often avoid using the double dollar function. For example the use case of attaching events to all ‘report this’ buttons on your site. The simple (and often good enough) approach would be to use the following code:
$$('.report_this').each(function(report_button) { var id = report_button.id.split('_')[1]; report_button.observe('click', this.respondToReportButton.bind(this, id); });
Four things are slowing this code down: 1. the usage of the $$ function, 2. the usage of each instead of a native looping construct, 3. the retrieving of the id from the id string, 4. the repeated binding of functions.
There are several possible remedies against the above code:
- Give all report_this buttons a unique id (say for instance that you have 15 or less in a list)
- Pre generate a list of ids using your server side language of choice and pass it to javascript
- Manually traverse the DOM; $(‘container’).childNodes can do wonders
- Bind once to a common parent element
- Find items by name instead of class
- Forget about all the initializing and fall back to old school onclick=”classinstance.respondToReportButton()”
This last option sort of goes against many webdevelopment principles, but is often a very pragmatic choice. Joseph Smarr from Plaxo holds a similar opinion on the topic.
A better implementation using technique 1 would be:
this.respondToReportButtonBound = this.respondToReportButton.bind(this); for(x=1;x<16;x++) { button = $('report_button'+x); if(!button) break; button.observe('click', this.respondToReportButtonBound); }
In practice I’ve experienced speed improvements of over 40 times using this technique. Firstly the repondTo function is bound only once. Secondly the $$ function is no longer needed. Thirdly the each implementation has been replaced by a blazingly fast for loop. Fourthly the id is no longer extracted. A better practice is to extract it when respondToReportButton is actually executed. This last point actually brings us to the next main item.
Step 2: Be Lazy!
The trick here is to actually put in a bit of effort to make your code lazy. Don’t do anything until it is needed. (With the one, but large exception if doing so would hurt the user experience.) If some items are currently not visible to the user simply don’t bind events to them. If you need to extract id’s don’t do so until someone actually clicks on the item in question. Furthermore also make it lazy in the regular sense of the word. If your code only need to change one item, figure out which one it is and don’t loop about changing all just in case. This point is different for every application, but it can achieve great speed gains for a creative programmer!
Step 3: Stop using prototype functions if you don’t need them
Often you do not really need (as in that it barely saves you development time) some of the functionality of prototype. When comparing the speed of element.innerHTML = ‘hello world’ versus element.update(‘hello world’) the differences are substantial (60 times with large chunks of html). Also the each iterator is often not needed and can be replace by a simple for loop with checks on nodeType and tagName. The same goes for the templating system. These tools barely save you time, but really hurt performance. I am a big fan of the prototype library and for most use cases these nice helpers are great. When you really need speed, be sure to refrain from using them though.
Step 4: Lower level optimizations
When you are done implementing the really important optimizations there are quite some lower level optimizations which will speed up your code.
- Write to innerHTML instead of using document.createElement
- Use for loops instead of for in loops
Use Array.join instead of += on a string, see SitePen- Cache variables and functions
- Limit the usage of Eval
- Limit the usage of Try Catch statements
- When manipulating the DOM copy the element out of DOM change it and stick it back in
Two generally great resources on the topic are:
The missing performance data
One item affecting the performance of javascript interface elements is the speed by which the browsers redraws the page. Unfortunately I have barely found any documentation on how browsers determine what to redraw and what affects redraw speed. One certainty is the negative influence of transparent images on redraw speed, but other than that little seems to be known. Furthermore most browsers won’t redraw the page until your javascript function returns. This can make your interface elements feel very unresponsive. A solution to this problem is to use the setTimeout functionality.
Message for Dutch Programmers
YouTellMe is an innovative startup located in the center of Rotterdam. Talented programmers are always welcome. Have a look at the job page to get an impression of the job openings (We develop using Python/Django).
Ajaxian » Some more JavaScript performance tips responded on 19 May 2008 at 12:09 pm #
[…] Schellenbach has written up some thoughts about JavaScript optimization for Prototype apps after playing with console.profile() / console.profileEnd() in his Prototype […]
solnic responded on 19 May 2008 at 12:33 pm #
Hello,
Regarding “Remove Double Dollar $$ and event binding” I’d say it is much better to use event delegation instead of attaching event listeners to each element, this is even faster and requires less memory.
Cheers!
tschellenbach responded on 19 May 2008 at 3:10 pm #
Hey,
Yes that is indeed a very nice solution.
I referred to it with point 4:
Bind once to a common parent element.
I am still not sure whether i prefer that or the old school onclick approach.
Cheers,
Thierry
Eiden responded on 19 May 2008 at 3:12 pm #
The templates in Prototype are very slow!
This little mod gives it a good perforance-boost :)
http://no-cache.net/?p=6
Jonah Dempcy responded on 21 May 2008 at 9:45 am #
Is it true that using the each() method has a considerable negative impact on performance?
I did extensive performance testing and tuning of a JavaScript app using MooTools and we found a few performance bottlenecks, but nothing with the each() loops. When compared to conventional core DOM methods, the each() loops had a negligible difference in time spent.
Also, out of curiosity, what are you using for profiling?
dtsn : Super Fast Prototype [javascript] responded on 21 May 2008 at 7:35 pm #
[…] If your a regular subscriber to my blog (and if you aren’t don’t forget you can subscribe here) you will know that I love Prototype, I was incredibly excited to see that Ajaxian had covered Thierry Schellenbach post about high performace JS apps. […]
Die goldenen Regeln für schnelle Prototype-Anwendungen | Ajaxschmiede.de responded on 21 May 2008 at 11:14 pm #
[…] BWL-Student und Javascript-Programmierer Thierry Schellenbach veröffentliche in seinem Mellow-Morning-Blog eine Abhandlung über geschwindigkeitsoptimiertes Entwickeln von Prototype-Anwendungen. Als […]
Prototype Javascript optimization to get best performance at AjaxApp.com, ajax app and cool web app! responded on 22 May 2008 at 12:12 pm #
[…] tips and those “NOT SUPPOSED TO DO” have been given by Thierry Schellenbach as listed below after he’s played with the functions console.profile() / console.profileEnd() […]
lillbra » Blog Archive » Tänkvärda tips om prestanda responded on 27 May 2008 at 5:25 am #
[…] Schellenbach listar prestandatips för javascript i artikeln Javascript optimization – high performance JS apps (via Ajaxian). För snabbare javascript bör man bland annat tänka på […]
Javascript optimization | Fomly responded on 27 May 2008 at 1:02 pm #
[…] Link:Javascript optimization – high performance JS apps […]
The art and science of performant Web 2.0 AJAX apps « Fluent.Interface responded on 09 Jun 2008 at 2:24 pm #
[…] JS libraries such as Prototype, JQuery etc. it can be easy to forget how expensive repeated DOM calls […]
GodLikeMouse responded on 18 Dec 2010 at 7:18 am #
Here are a few optimal JavaScript techniques to keep in mind code wise.
http://www.godlikemouse.com/2007/12/13/optimization-techniques-for-javascript/
These techniques involve more changing the implementation of code and the way loops execute, object instantiation, etc.
Übersetzer| responded on 14 May 2012 at 4:55 pm #
grüß Gott Personen, hierbei habe meine Wenigkeit eine haarlocke revulotionäre Mitteilung Flanke sondern songtext sprachmittler
plus übersetzungen aller Erscheinungsform.
Bessere Seiten habe selbst nicht gesehen noch dazu empfehlungen spreche
selbst außergewöhnlich aus. Texte u. a.
Verse vulgo sprüche können zu dieser Gelegenheit übersetzt zustandekommen.
Zeit sparend unter anderem nachrangig dichtgenügsam in welcher Handhabung.
Blagen zumal Ruheständler freundliche Anwendungen sind 1A zum Übersetzen Übersetzer|
Manjushri Chauhan responded on 08 Dec 2012 at 5:44 am #
Wow! This blog looks exactly like my old one!
It’s on a entirely different subject but it has pretty much the same layout and design. Wonderful choice of colors!
dragonvale dragons responded on 24 Jul 2013 at 5:42 pm #
At this time I am going away to do my breakfast, after
having my breakfast coming over again to read further news.
Donny responded on 02 Apr 2014 at 3:32 pm #
hello there and thank you for your information – I have definitely picked up something new from right here.
I did however expertise some technical issues using this website, since
I experienced to reload the site a lot of times previous to I could
get it to load properly. I had been wondering if your web
hosting is OK? Not that I am complaining,
but slow loading instances times will very frequently affect your
placement in google and could damage your high quality score if ads
and marketing with Adwords. Well I am adding this RSS to my email and could look out for much more of your respective exciting content.
Make sure you update this again very soon.