PermaLinkA big JavaScript speed pick-up03:30:31 PM
Written By : Scott Good

We are in the middle of big project rewriting the web interface used by Insurance Agents to quote, order, and manage Auto policies for their clients. I can't go into a lot of details about the specific application but suffice it to say JavaScript Performance there are a lot of fields on the form and that the code needs to access and re-access those fields over and over and over again.

That's easy to do with JavaScript, of course, but (there's always a "but")...when you do LOTS of this things tend to get slow.

Really slow.

Because we're writing this application as the base for a number of other products offered by our client, we have purposely built flexibility into it. So, where you might otherwise have hard-coded the number of vehicles or drivers, we have purposely built this application so those numbers can easily be changed. I already wrote about other aspects of this capability in a previous entry here.

Once you have all the flexibility of dynamically allowing the number of fields on the form to change, you can't exactly hard-code access to the fields (as the number of them can change at any moment). In JavaScript, that means you have to use a lot of eval() statements in your code, more or less like this:

var fieldRef;
for (var i = 1; i <= maxDrivers; i++){
    fieldRef = eval("document.forms[0].DriverFirstName" + i);
    // then do something here with fieldRef
}

Pretty standard stuff except that, as I said, it can be really slow, particularly if you need access to the same fields over and over again, which we do.

So, we came up with what has turned out to be a spectacularly successful (if I may say so) work-around.

It's not only that eval() is slow (which it is, particularly in IE), but also that you have to do it over and over again for the same field object. That's slow and inefficient. Happily, the solution is a model of simplicity: We built an array of pointers to fields.

Initially, the array has no values. When you ask for a pointer it first checks to see if it already has one to that particular field. If so, it returns the pointer (without having to go get it again). If it doesn't already have a pointed to the field you're looking for, the code creates the pointer, adds it to the array, and returns the pointer to you. Here's the code:

var getFieldObjList = new Array();

function getFieldObj(fName){
    if (getFieldObjList[fName] == null){
        getFieldObjList[fName] = document.forms[0][fName];
    }
    return getFieldObjList[fName];
}

That's it.

In your code, you substitute...

getFieldObjList(...)

...for...

eval("document.forms[0]....")

...and it just works.

How well, you ask? In Internet Explorer (where this is most valuable), this technique cut the time to access 302 fields 26 times each (7,852 total accesses) from 2,994 milliseconds to 181. If you don't have your calculator handy, that's over 16 times faster.

In Firefox, the same code goes from 590 milliseconds to 181, a measly 3-times faster. So, it's good in Firefox but great in IE (or, more to the point, Firefox is a lot more efficient at evaluating code than IE).

If you're building complex JavaScript-intensive applications, you may want to consider adding this to your toolbox.

Comments :v

1. Rich Waters12/28/2006 04:47:00 PM
Homepage: http://www.rich-waters.com/blog/


I think the first question is why are you retrieving the fields over and over again?

I would hazard a guess that it would be more efficient to create an (javascript) object for each driver that has properties for name, address, etc.
This way you could create an array of objects and the data would already be stored in memory for javascript, relieving the need to traverse the DOM every time you wanted at a value. Though this would require some event handling if you needed the javascript values to stay up to date with the values that the user enters on the page.

Accessing the DOM should always be minimized when looking for best performance in a javascript heavy application.




2. Jack McKensie12/28/2006 05:10:30 PM


simpler to do this and be done with it:

fieldRef = document.forms[0].elements['DriverFirstName' + i];

No need for any global array of field references, they are already accessible from the DOM as above.




3. Scott Good12/29/2006 07:26:13 AM
Homepage: http://www.scottgood.com


@Rich: You may be right about creating objects for all the drivers and vehicles and such but I'm a little skeptical, at least in this application. While it probably wouldn't be necessary to keep the JavaScript objects in synch with the fields during editing (hm...maybe, maybe not), I'm not sure what benefit the objects would give you if you didn't because, ultimately, we're reading and updating field values here.

I can't see how keeping everything in synch with changes to the fields wouldn't add overhead, slowing the process a bit. Whereas I'm tracking nothing more than pointers to the fields, with your approach I'd have to update the objects in memory as well as the fields on the form. While that's not a lot more work it's still more work.

Also, the way this application is built there are duplications of data in places. For instance, some driver and vehicle information is carried over to a summary page. Any adjustments made in one place have to be pushed to the other, which requires a handle to the appropriate (secondary) field.

@Jack: Your approach works--and is measurably faster than using eval()--but in my testing it's pretty slow compared to the approach we're using. In a quick comparative test, my code ran in 181 milliseconds (8,000 field accesses) compared to 2,234 for yours. That's about 20% faster than using eval() (2,854 milliseconds), but about 45% slower than using hard-coded field names (1,540 milliseconds), and a bit more than 12 times slower than our approach (in IE 7, at least).




4. Rich Waters12/29/2006 11:10:51 AM
Homepage: http://www.rich-waters.com/blog/


Indeed, I made my comments without really knowing much about the application or what you were trying to accomplish. I was merely trying to point out that using fields on a page to store large amounts of data is not the most efficient. It's going to be much faster to access the data directly from javascript data structures. Especially if its not necessary to keep the display up to date. I see the idea behind using fields so that you can just normally submit the page to save changes, but its not much harder to push javascript data back to a server.




5. Scott Good12/29/2006 12:42:54 PM
Homepage: http://www.scottgood.com


Interesting. In this application I don't think that would work because the fields are needed for actual editing, but I'm interested in how you would use JavaScript to directly push data back to a Domino server. I've done it through iFrames using either forms or agents or both, but your post kinda sounds like you might have another scheme up your sleeve.

Scott




6. Rich Waters12/29/2006 06:08:05 PM
Homepage: http://www.rich-waters.com/blog/


On an application I was recently working on I pieced together a rough framework for making ajax calls to save changes to single or multiple documents. Mainly consisting of a couple of Java agents that processed post values from the ajax call and made the corresponding changes to documents. For the front-end I wrote a few wrappers on top of Prototype ( http://prototype.conio.net ) that boiled things down to some simple javascript functions that could be called to update fields on documents.
The main driving force for designing it that way was to ease changing fields across multiple documents at once. I also used the agents to process updates made from inline editing components that we added to several places throughout the application.

This is similar to how the DomYUI OpenNTF ( http://www.openntf.org/projects/pmt.nsf/ProjectLookup/Domino%20YUI ) project I recently started working on is going to add in inline editing capabilities to the data grid. (hopefully available in the next release)




7. Scott Good12/30/2006 08:06:31 AM
Homepage: http://www.scottgood.com


That's very interesting stuff! Let me know if you want some help on it.

Scott




8. Jack McKensie12/30/2006 07:53:01 PM


I remember reading on the IE Blog that repeated access to nested properties was slow and you should cache where possible so if you cached the reference to

document.forms[0].elements

You could do this:

var getFieldObjList = document.forms[0].elements;

and it should be just as fast. I'd be interested to know if it is.




9. Scott Good01/02/2007 08:53:29 AM
Homepage: http://www.scottgood.com


Jack,

From my quick testing, it's certainly better that way. It improved from 2,200 milliseconds to the point it's about the same as using hard-coded field names (1,500 milliseconds or so).

Of course, it's possible I'm not doing it right. Here's what I've done:

1. Created a global JS variable called documentElementsList as a blank array.

2. In the onLoad event, did this: documentElementsList = document.forms[0].elements;

3. In my loop, called for objects from the documentElementsList like this:

for (var x = 1; x <= 8; x++){
fieldRef = documentElementsList['DriverFirstName' + x].value;
}

Does that look right to you? It's interesting it made that kind of difference, even if it's not up to speed of the array of objects. Actually, the more we play with this, the more shocked I am at how well my little scheme is holding up...I did it the way I did only because I couldn't think of another approach. Lucky guess!

Thanks,

Scott




10. Scott Good01/02/2007 10:49:55 AM
Homepage: http://www.scottgood.com


Jack,

An update: Your code is almost exactly as fast as my code in Firefox.

Scott




11. Jack McKensie01/04/2007 08:46:31 PM


Hi Scott, this has been an interesting excersize!

I think it highlights the differences in the way the browser makers have done the bindings between the javascript compiler and the internal memory locations. I wonder if in IE document.forms[0]['element'] is more efficient than document.forms[0].elements['element'] ...hmmm




12. Scott Good01/05/2007 08:38:07 AM
Homepage: http://www.scottgood.com


Jack,

Just tried it. document.forms[0].elements['elementName'].value is 2,264 milliseconds (8,000 reads) vs 1,392 for the cached elements vs 170 for the array of objects (all in IE 7).

In Firefox, the same three are 1,001/621/551 ms.

So...either way you go ...elements['elementname'] is not a good value.

I have to say, though, I've learned a whole lot of new ways to access objects in JavaScript that I didn't know before we all started playing with this. As you say, very interesting.

Scott




Enter Comments^


Email addresses provided are not made available on this site.





You can use UUB Code in your posts.

[b]bold[/b]  [i]italic[/i]  [u]underline[/u]  [s]strikethrough[/s]

URL's will be automatically converted to Links


:-) :cry: :-\ :huh: ;-) :cool: :grin: :emb: :laugh: :-p :lips: :-( :rolleyes: :-o :-D :angry: :-x
bold italic underline Strikethrough





Remember me    

Disclaimer & Copyright
Monthly Archive
Contact me...
Racing sponsors and such...

Thank you sponsors!

GABlogLogo.jpg

GOODAero

GOODAero specializes in building aerodynamic products for racing cars. Our first product, the GOODAero Raptor wing is available at a surprisingly reasonable price (under a grand) for a full carbon, full-sized, racing wing. Check it out.


Infinite Fiberworks Co, a great source for high-quality Porsche fiberglass parts

Infinite Fiberworks Co.

If you are looking for fiberglass for Porsches, IFC is the place to go. I have used parts from most of the major suppliers and IFC's are easily the highest quality and the most reasonably-priced. Contact Mike at Infinite Fiberworks for more information.

Located in Racine, OH (so far Southeast they're almost in West Virginia), IFC's goal is to be The Best. Give 'em a try.


Bent or ugly wheels? Call Wheel Medic!

Wheel Medic & The Round House

Whether you need to repair, repaint, refinish or just replace your wheels, the guys at Wheel Medic/Round House can get you back on the road in no time!

Wheel Medic, Inc is a family-owned company which specializes in the repair and restoration of aluminum wheels.

The Round House was founded to service Wheel Medic's clients looking for more than just repair work...from custom wheel colors to high-end wheel applications and body kits, the Round House is there to serve the discriminating automotive enthusiast.


Used Porsche parts, great prices!

A Part Above

Looking for used parts for 944s, 924s, 968s or other late-model water-cooled Porsches? Contact John at A Part Above.

Located in Strongsville, OH (20 miles south of Cleveland) their goal is to provide top quality parts and services. I can tell you, John is great to work with and the prices? Very hard to beat.


SMRT Motorsports wants you!

SMRT (that's short for Skid Mark Racing Team), a very-

loosely organized band of fun-loving friends who enjoy auto racing (heck, cars in general), and the occasional adult beverage, wants you to be a part of our team.

Go here to find cool T-shirts, sweatshirts, caps and mugs with the SMRT team logo.

The BlogRoll
Lotus Domino ND6 RSS News Feed RSS Comments Feed Geo URL RSS Validator Blog Admin Lotus Geek Open Notes Picture Database OpenNTF BlogSphere
Calendar
February 2012
Su
Mo
Tu
We
Th
Fr
Sa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
By Category
What I do for a living


I am the President of Teamwork Solutions a long-time Lotus, now IBM, Premier Partner.

With offices in Columbus and Cincinnati, Ohio, we specialize in custom application development for IBM Lotus Notes, Domino, and related technologies. Our software product, ProcessIt! (see below), is quite possibly the world's best, most powerful and easiest-to-use workflow tool for Notes and the web.

Our clients are some of the world's largest corporations along with others that aren't so big.

We do excellent work, quickly, and often on a fixed-fee basis. We'd love to talk to you about your next project.




I am a Contributing Author to Lotus Advisor Magazine, with more than 40 articles under my belt.

I've written how-to series (serieses?) on LotusScript, JavaScript, Cascading Style Sheets (CSS), and now, AJAX (Asynchronous JavaScript and XML), as well as a bit on miscellaneous web development topics.


TheView.jpg

I also write for The View as of the July/August issue where I showed how to take an ugly Notes applications and make it beautiful with just a few minutes' (careful) work.



I am the chief architect and one of two primary developers for what many consider the best all-around workflow tool for Notes/Domino, anywhere, regardless of price.

It's called ProcessIt!, and you can read all about it at www.notesworkflow.com but the bottom line is this: ProcessIt! is fast and easy to learn, extremely powerful, and can be used by mortals. Even--dare I say it?--common users.

You can spend a lot more on a workflow tool but you won't be able to do a lot more for all the extra money.

Don't believe me? Download and try it for free for 60 days.



GTSLogoSm.gif
Copyright Porsche and NASA...not me!

I race a Porsche 944 S2 in National Auto Sport Assocation events and am the 2008 National Champion in NASA's GTS2 class.

Blame this event, a few years ago, for starting that particular money drain all over again.

In support of my habit, I am the NASA Great Lakes Region's GTS (German Touring Series) Director.

I'm also a Nationally-Certified Instructor for the Porsche Club of America and am in charge of classroom sessions for the Mid-Ohio region when we are doing high performance driving events.

In a prior racing life, I was the Midwestern Regional Formula Atlantic Champion and, in 1991, the Ohio Vally Region of SCCA's Regional Driver of the Year (but that, alas, went away when my credit cards let go of the rope!).




I'm writing a book...or at least trying to.

It's murder mystery in which, not too surprisingly, the main character runs a small software company and races cars for fun. Oh yeah, and lives near where I do.

Just where do they come up with these crazy ideas?

Facebook