Javascript performance notes

Posted in javascript by Kris Gray on April 10th, 2007

Getting information on JavaScript performance really is like finding a female programmer. (No punchline to protect myself from the females.) So excuse me if you’ve heard some of this before, but for those JS Perf virgins out there here’s some of the notes I’ve compiled.

Caching

In Javascript you can copy references to Arrays, Functions, Dom elements, anything and once you have that element cached in a local context, you avoid some icky lookups. having lots of periods in a reference (sys.ajax.enums.serverparsed.transformers.optimusprime) creates a lot of object lookups that will hit you on every lookup. In the grand scheme of things, this isn’t that big of a problem, often you won’t be doing any operation often enough that the milliseconds this call would save in any particular call, but something to keep in mind.

Don’t hit the Dom

The last big script application I wrote was an excel like application, so on some occasions there were 450 x 60 (27,000) cells on the page, which I would have to iterate over and perform some operation. In this application the number one performance gain was to cache the properties of each cell and determine if any operations are necessary based on that cached version. Avoiding .innerHTML for reading, not using getAttribute, setAttribute for storing information about the cell, and don’t store references to script manager objects on the dom object.

Prototype’s

The difference here is memory, you only need one instance of a function, unless for some reason you construct the string of the function, but for the most part, if you use prototypes you’ll only get the one instance of the function instead of an instance for each instance. Got it?

Loop backwards and Duffs Device

Put this in the “Almost to small to care” folder. Looping backwards for some reason, gets you a few milliseconds on your loop. Duffs device is a method of executing the same code while not needing to loop quite as much. Its worth it in loops of several thousand iterations, but overall it hurts readability and bloats the code, so look for gains elsewhere.

switch (count % 8)  /* count > 0 assumed */ { case 0:        do {  *to = *from++;

case 7:              *to = *from++;

case 6:              *to = *from++;

case 5:              *to = *from++;

case 4:              *to = *from++;

case 3:              *to = *from++;

case 2:              *to = *from++;

case 1:              *to = *from++;

}  while ((count -= 8) > 0);

}

Manager Objects

In this aforementioned excel like application, I adhered to an object oriented methodology, which turned out to be neurotic. This application ended up having thousands of objects in memory just to manage each cell. It would have been much smarter to have one object that manages all these thousands of cells. This also allows for removing the reference on the dom object to their individual script object instance. Instead I would put just a string identifier on the object which I would use to get from a hash.

var scope

This should be in the obvious section, but if you don’t use var when declaring your variables, the JS engine searches up the chain looking for a property to set, and if it doesn’t find it, then it uses a global variable on the window. At which point references to the variable become global property lookups.

Leaky Memory

Memory holes are causes by circular references that confuse the garbage collector. Namely, DomElement -> Script Object -> Dom Element. Avoid at all costs, if you need, save a string id on the Dom element, and use that to retrieve the script object when you need it.

function Obj(xEl) {

 this.Ref = xEl;

}//--- Memory hole in the making

document.getElementById("el").xScript = new Obj(document.getElementById("el"));

eval()

Everyone knows this is already a performance hog and you shouldn’t use it. Not sure why? Well, when the page loads it goes through all the Script on the page, parses it and loads it then shuts down so the page can go about the rest of its business. When you eval, you start this loading engine again, and this is as heavy a process as it sounds. While not as evil, the new Function(“”) constructor is just as evil, it uses an eval to construct a function from a string value. Never eval to get a variable reference, you can use the bracket structure to pass the name of the variable to its parent object

window["location"]["href"] = "http://www.blackbeltcoder.net/"

If you can think of any others, please post a comment and we’ll get those added. I’ll probably add a part 2 as I remember a few other tricks.

2 comments

The troubles of reaching Sashimi.

Posted in scrum by Kris Gray on April 5th, 2007

Sashimi, in the Scrum religion is a term used to indicate a bit of completed functionality. Yet the meaning of completed in this instance is up to some debate, according to Ken Schwaber an old veteran and founding father of Scrum…

This introduces the concept of sashimi, a slice of the whole equivalent in content to all other slices of the whole. For the Daily Scrum, the slice of sashimi is a report that something is done. “Done” implies accepted engineering practices that indicate that done means coded. Or maybe it means coded, unit tested, checked in, built, and acceptance tested. Either way, there must be a common understanding; otherwise mistakes may be made as various team members inappropriately adapt based on incorrect assumptions of what they inspected. Similarly, the increment created every iteration must be well-defined and similar every time. In Scrum, each increment is an increment of potentially shippable product functionality.

-Ken Schwaber (http://www.coldewey.com/publikationen/conferences/oopsla2003/KenSchwaber.pdf)

So at the end of each iteration, you should have shippable product consisting of the sashimi of the last sprint. If you think about this in terms of pieces of fish and dinner, everything works great, if you think of this as programming the next version of Windows, your not going to have shippable product after a single iteration, does this mean Scrum won’t work for large projects? Or even projects that will take longer then one sprint? Not if we refine the definition of Sashimi.

  • Development Sashimi

This is the amalgamation of all the completed work from the last iteration. This may not be shippable, but you can see the value of the time spent on the iteration, so its important to keep cranking these out. If your sprint is as short as a week, you will have quite a few of these before reaching the all important product owner sashimi.

  • Product Owner Sashimi

At some point you will complete an iteration and the collection of the development sashimi iterations will be shippable. This is the milestone thats super important, up until this point your feature is in limbo and cannot be shipped. Its important to get here as soon as possible, the longer your in limbo you issues and can’t get all the full benefits of the normal scrum process. You can’t shift priorities (as all the previous work is wasted), you can’t ship your active source tree and you have the ability of feature/scope creep.

This seems to imply that you should never do a sprint that you couldn’t get PO Sashimi from, which is highly favorable but impossible for more reasons then I have time to document here. Just keep on the lookout for these stages, and scrum away.

No comments

« Previous Page