Pre-compile and cache yer dang regular expressions

We have a function called hasClassName(el, cls) that checks whether a given DOM element has a given class. More and more, we're relying heavily on this function, and on certain pages it can run thousands of times. In these situations a little performance tuning can go a long way, as demonstrated here:

// BEFORE
function hasClassName(el, cls){
  var exp = new RegExp("(\^|\\\\s)"+cls+"($|\\\\s)");
  return (el.className && exp.test(el.className))?true:false;
}
// AFTER
(function(){
  var c={};//cache regexps for performance
  window.hasClassName=function(el, cls){
    if(!c[cls]){c[cls]=new RegExp("(\^|\\\\s)"+cls+"($|\\\\s)");}
    return el.className && c[cls].test(el.className);
  }
})();

This simple change cut the function's average runtime in half and reduced the page's overall onload setup time by over 25%! (According to Firebug.) All because it caches regular expressions.

Edit: removed unnecessary ?: operator per Nate's comment.

Comments:

Why the ?: why not just return the test?

Posted by Nate on January 28, 2008 at 11:15 AM MST #

@Nate

Some have told me they leave the literals there for clarity; I've also seen CS grads who didn't realize you didn't need the literals.

@greimer

Thanks for the tip, but having encountered similar constructs in the past, I'm curious if there's a "break-even" point, where once you get N elements in the cache it'd be slower to look them up than to exec them fresh? Other than testing, is there a way to compute this?

Posted by kenman on January 28, 2008 at 06:33 PM MST #

@kenman

From experience using an Object as an associative array like that in Javascript is pretty scalable. If you're dealing with such a large number of RegExp calculations that you hit the limits of Javascript Objects then you're doing something pretty intense indeed.

I don't know of a way to compute it other than testing, since performance will differ in different browsers. Give it a go. Let us know what you find.

Posted by Richard on January 29, 2008 at 01:00 AM MST #

@kenman

I've benchmarked JavaScript performance with objects containing ten thousand properties, and adding new properties and property lookup still appears to be on the order of O(1), and performs well into the sub-millisecond range.

@Nate

I honestly can't remember why I used the ?: instead of just returning the test. It's probably a vestigial holdover from the early days of the function. :P

Posted by Greg on January 29, 2008 at 02:27 AM MST #

@myself

Actually I should be careful using computer-sciencey terms like O(1). My benchmarks probably weren't scientific enough to come to that conclusion. However I stand by the "well into the sub-millisecond range" statement.

Posted by Greg on January 29, 2008 at 02:38 AM MST #

Post a Comment:
Comments are closed for this entry.
About

My name is Greg Reimer and I'm a web technologist for the Sun.COM web design team.

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
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
30
   
       
Today