Access Keys:
Skip to content (Access Key - 0)
Home (Access Key - 1)
All spaces... (Access Key - 3)
Log in (Access Key - 5)
Sign up (Access Key - 6)
Toggle Sidebar

News from Jan 12, 2008

blog entry  2008/01/12
Last changed: Jan 12, 2008 05:17 by Guy Fraser

A while back I posted a link to the awesome DateJS library on my JavaScript page. Around that time I also looked at the code to see if there was any way to reduce the file size and possibly tweak the performance a little...

Geoffrey McGill from Coolite (where DateJS was developed) asked me if I'd blog about some of my findings but I never got round to finishing my post - so here it finally is, mostly compiled from emails that were exchanged at the time.

Performance

I'll start with this as it's the shortest topic in the blog and one that will possibly freak some people out. It's a trick I used back in the days of ActionScript 5 (slow performance) programming to get both surprising performance gains and also reduce the amount of typing I was doing!

A nice trick

See if you can spot the performance hit with the following code:

Date.prototype.clone = function () { ... };

Date.prototype.compareTo = function (date) { ... }

Date.prototype.equals = function (date) { ... }

Date.prototype.between = function (start, end) { ... }

Date.prototype.addMilliseconds = function (value) { ... }

It's a trick question, there are actually two performance hits, both of which we can quickly eradicate:

  1. The first is that each time you reference Date that global object has to be located.
  2. The second is that each time you reference the .prototype object on Date, you're forcing the JS engine to go find .prototype.

So, how do we fix this? Simple:

var DP = Date.prototype;

DP.clone = function () { ... };

DP.compareTo = function (date) { ... }

DP.equals = function (date) { ... }

DP.between = function (start, end) { ... }

DP.addMilliseconds = function (value) { ... }

Because DP is a local variable, it's faster to reference. Because you're not looking for the .prototype object repeatedly, it's faster still. As an added bonus, you generally type fewer characters and the file size also shrinks.

Give it a try - you'll be surprised, especially on big libraries.

Here's what Geoffrey says:

Your original suggestion re: var DP = Date.prototype made a big impact on the size (and performance) of the library. ....just changing to holding a reference to the Date.prototype, we shaved approx 1.2k off the total library size. That translates to ~4.5% size reduction. And, it's faster!

You can apply the technique to all sorts of things. You could argue that it can somewhat obfuscate your code, which it probably would if you use it excessively, however it should be possible for automated tools to implement the optimisation at build/runtime leaving your development code unaltered.

Running backwards (might be out of date)

Another trick I used to use was, where possible, iterating through arrays backwards using a while loop. For example:

var x = someArray.length;
while (-1<--x) {
 // do stuff
}

The variable x is used for aesthetic purposes, (-1<--x) just looks sweet IMHO, there's a "backwards flow" to it which I find strangely relaxing.

This was generally quicker than most other types of loop back in the day, but I've not had chance to test it against modern JS engines - if you test it, please let me know the results!

Shrinking the file size

My next mission was to see if I could shrink the file size of DateJS. I started with core-debug.js from the following URL:

http://datejs.googlecode.com/svn/trunk/src/

As the files will have changed a fair bit since then, I've attached them to this post.

1. Manual Filesize Reduction

I edited the file to replace some verbose repetitive code with while loops and also created a shortcut to Date.prototype. Diff the files to see what's changed. This resulted in core-guy.js:

core-debug.js (original version): 24.9 KB
core-guy.js (my version): 23.4 KB

Result: New version is a bit smaller

NB: I've not tested the core-guy.js version so it could contain bugs - if there are any they should be easy to fix.

2. JSMIN vs. /Packer/ (No, it's not what you think, don't jump to conclusions!)

Before instantly assuming /packer/ is bad: THIS IS A LIKE FOR LIKE COMPRESSION - ie. /Packer/ doing the same sort of things as JSMIN, nothing more, no Base62 or variable shrinking.

I downloaded the core.js file which used JSMIN (so I renamed it to core-jsmin.js for clarity) and compared it to Dean Edwards's /packer/ at http://dean.edwards.name/packer/ using the most basic packing (whitespace, etc).

core-jsmin.js (JSMIN version of core-debug.js): 9.64 KB
core-pack.js (/packer/ version of core-debug.js): 9.18 KB
core-guy.pack.js (/packer/ version of core-guy.js): 8.01 KB

Result: Packer versions are smaller

Again, I've not checked the packer versions - it's quite strict on syntax but any bugs should be easy to fix.

3. Even smaller: /Packer/ + Shrink Variables - gzip friendly!

The /packer/ also has a "shrink variables" option, which isn't available in JSMIN as far as I know...

core-jsmin.js (for reference): 9.64 KB
core-pack.shrink.js: 8.46 KB
core-guy.pack.shrink.js: 7.25 KB

Result: Packing + Shrinking is even better

There's no performance hit - all it does is intelligently shrink internal variable names.

The packed + shrunk variables version is perfect for use with gzip compression (ie. gzip will make it even smaller). This has been proven by jQuery and many jQuery plugins - yet most developers think that using "Shrink Variables" will make the gzip compression less effective.

4. Super-small for non-gzip scenarios

For scenarios where gzip isn't available (for whatever reason) the /packer/ also has a Base62 encode option:

core-jsmin.js (for reference): 9.64 KB
core-pack.shrink.base62.js: 5.66 KB
core-guy.pack.shrink.base62.js: 5.33 KB

Obviously, the Base62 option does have a performance hit - anything up to 200ms while it "unpacks", but then again in scenarios where you can't use gzip shaving a few more Kb's off the file size will probably make up for that. Once the unpacking is done there's no further performance hit.

Whether you use my tweaked core or the original core, the /packer/ gives a much smaller file for non-gzip use.

And finally...

I also used CompressorRater (http://compressorrater.thruhere.net/) to check core-guy.js against various other compression methods and /packer/ still gave the best results.

Some tips for packer

Don't discredit it because of the bad things you've heard about Base62 compression - that's an optional feature that you'll very rarely need and should you need it, you'll be thankful it exists!

Always put a semicolon on a new line at the start of your script to allow it to be safely merged and packed with other scripts.

Always put a semicolon at the end in scenarios like the following:

// bad:
var foo = function { ... }

// good:
var bar = function { ... };

Packer could chimp otherwise.

Posted at 12 Jan @ 3:57 AM by user Guy Fraser | comment 0 comments
Last changed: Jan 12, 2008 05:30 by Guy Fraser

I was speaking to Peter Reiser earlier today about jQuery performance and mentioned a couple of tips that he asked me to blog about...

Give the latest nightly build a try

People testing the latest nightly builds are all saying that jQuery 1.2.2 is definitely faster than 1.2.1.

More info on the nightly builds and SVN here: http://docs.jquery.com/Downloading_jQuery

Tune your selectors

If you've got big web pages it's well worth making your CSS selectors more specific so they do less work.

First, try and limit them to a sub-section of the DOM, for example:

jQuery('.foo',context).whatever();

Where context is either a DOM element or a jQuery object. This instantly shrinks the number of elements jQuery has to wade through.

Second, think about the actual selector - is there something more specific you could use to reduce the number of elements searched?

For example, if you use '.foo' as shown above, jQuery has to search every element just to see if it has a "foo" class. If you know that you only want to find <div> elements with the "foo" class, use this instead:

jQuery('div.foo',context).whatever();

Learn from the speed tests

Before doing this, please note that the speed test results are very easily misinterpreted. People often think one library is worse than another if it seems to have poor speed test performance which is a naive assumption to make - the speed tests don't show real-world scenarios for which jQuery is superb and possibly only beaten by ExtJS.

Here's the speed test: http://www.kenzomedia.com/speedtest/

What you're looking for are the selectors that take the shortest time in jQuery - identify the trends and find out what's faster and slower in terms of the selector syntax then see if you can use that to improve your selectors.

Posted at 12 Jan @ 4:41 AM by user Guy Fraser | comment 1 comment
Last changed: Jan 22, 2008 06:58 by Guy Fraser

As you can probably guess by the three-in-a-row blog posts, the tedium of doing the end-of-year accounts as well as the painstaking process of beta testing new versions of Theme Builder and Community Bubbles has taken me to the point where I could just scream. That would wake the wife up (it's nearly 5am) and she'd scream at me and probably throw something at me too. For the sake of everyone involved, I'm blogging!

We've had plans to revamp our website design for a while and as you can now see, the transition is pretty much complete. The page graphics have been floating around for almost a year but we've only just got round to implementing it. This time we decided to do a tutorial of the four stages.

Which brings me nicely on to...

New Community Spaces

We've been wanting to set these up for ages and get them in to a fit state for public consumption, and we've finally made some progress.

We set up our Theme Builder forum space a while ago, but it was a bit sparse. If you've not checked it since, go take a look now: Theme Builder community

Likewise, we've also added a Community Bubbles community which is worth a look because for the first time we're doing some of our development work publicly so customers can participate in the process and make sure we don't mess up what is a small but surprisingly difficult development task (it looks simple on the surface, especially now most of the concept pondering is complete, but it's been a real nightmare to do).

In addition, we've revamped the Scriptix community, adding a forum and some improved navigation.

We're hoping to achieve the following with the the new community spaces:

  • Allow users of the plugins to more readily communicate and share ideas
  • Provide a single source for the latest news and information
  • Make it easier to find resources related to a specific plugin
  • Hopefully offload some of our huge customer support workload in to the public forums (seriously, this would really help us roll out product updates far more quickly if you start chatting in the forums!)

By watching the community spaces, you effectively join a mailing list and hook in to all the latest tutorials, forum discussions and news for the associated plugin.

I'm giving serious consideration to moving the user guides for the Builder and Bubbles plugins in to their respective spaces to really bring everything together, but I'm not sure if it would lead to too much noise in terms of change notification emails for people watching the space. What do you think?

As part of the recent community space binge, I've also turned my blog in to a forum/community too!

Right, I'm probably going to be in "Monk Mode" for the rest of January, locked away in a dark room chanting and performing strange rituals... Unless said activities once more drive me to a blogging frenzy!

Posted at 12 Jan @ 5:19 AM by user Guy Fraser | comment 3 comments
Last changed: Jan 12, 2008 18:32 by Guy Fraser

Blame Charles Miller for this one (and Dan Hardiker for telling me about it)...

How to create your album cover:

  1. Your band name is the title of your first hit on Wikipedia's random page
  2. Your album name is taken from the end of the last quote on this random quotes page
  3. Your album cover must be made from the fourth picture on Flickr's interesting photos page

For me, that was:

  1. Circuba
  2. Some mornings it just doesn't seem worth it to gnaw through the leather straps.
  3. I sublimate my rage through needlework

I decided to leave the whole quote intact, although I suppose "Gnaw through the leather straps" would have been equally satisfying.

@Charles Miller: What is it with you and cheese anyway? You sure you didn't fudge your album cover? Are you perhaps trying to convince computers that it is they who like cheese?

Posted at 12 Jan @ 6:27 PM by user Guy Fraser | comment 1 comment

next Jan 12, 2008
previous Jan 12, 2008

Toggle Sidebar

Adaptavist Theme Builder Powered by Atlassian Confluence