Skip to content

Commit

Permalink
add some basic perf tests
Browse files Browse the repository at this point in the history
  • Loading branch information
slevithan committed Aug 14, 2012
1 parent ab2cd6a commit 34d5d50
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 10 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@


XRegExp provides augmented, extensible JavaScript regular expressions. You get new syntax, flags, and methods beyond what browsers support natively. XRegExp is also a regex utility belt with tools to make your client-side grepping simpler and more powerful, while freeing you from worrying about pesky cross-browser inconsistencies and the dubious `lastIndex` property. XRegExp provides augmented, extensible JavaScript regular expressions. You get new syntax, flags, and methods beyond what browsers support natively. XRegExp is also a regex utility belt with tools to make your client-side grepping simpler and more powerful, while freeing you from worrying about pesky cross-browser inconsistencies and the dubious `lastIndex` property.


XRegExp supports all native ES5 regular expression syntax. It's about 3.6 KB when minified and gzipped. It works with Internet Explorer 5.5+, Firefox 1.5+, Chrome, Safari 3+, and Opera 11+. You can also use it on the server with Node.js. XRegExp supports all native ES5 regular expression syntax. It works with Internet Explorer 5.5+, Firefox 1.5+, Chrome, Safari 3+, and Opera 11+. You can also use it on the server with Node.js, or as a RequireJS module. The base library is about 3.8 KB, minified and gzipped.




## Performance ## Performance


XRegExp regexes compile to native `RegExp` regex objects, thus there is no performance difference between the two. There is a small extra cost when compiling XRegExps. If you want, you can use `XRegExp.cache` to avoid incurring the compilation cost again for a given pattern and flags, across your entire application. XRegExp regexes compile to native `RegExp` regex objects, thus there is no performance difference between the two. There is a small extra cost the first time you compile a particular pattern and flags.




## Usage examples ## Usage examples
Expand Down
7 changes: 3 additions & 4 deletions src/xregexp.js
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -431,11 +431,10 @@ var XRegExp = (function(undefined) {
return ''; return '';
}); });


// Throw on unknown native or nonnative flags
for (i = 0; i < flags.length; ++i) { for (i = 0; i < flags.length; ++i) {
chr = flags.charAt(i); if (!registeredFlags[flags.charAt(i)]) {
// Throw on unknown native or nonnative flags throw new SyntaxError(ERR_UNKNOWN_FLAG + flags.charAt(i));
if (!registeredFlags[chr]) {
throw new SyntaxError(ERR_UNKNOWN_FLAG + chr);
} }
} }


Expand Down
150 changes: 150 additions & 0 deletions tests/perf.html
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,150 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>XRegExp Perf</title>

<!-- XRegExp -->
<script src="../src/xregexp.js"></script>
<script src="../src/addons/build.js"></script>
<script src="../src/addons/matchrecursive.js"></script>
<script src="../src/addons/prototypes.js"></script>
<script src="../src/addons/unicode/unicode-base.js"></script>
<script src="../src/addons/unicode/unicode-blocks.js"></script>
<script src="../src/addons/unicode/unicode-categories.js"></script>
<script src="../src/addons/unicode/unicode-properties.js"></script>
<script src="../src/addons/unicode/unicode-scripts.js"></script>

<!-- Very basic benchmarking, adapted from <https://github.com/visionmedia/js-bm> -->
<script>
(function(){
var currentSuite;

function pad(str, len) {
return str + (new Array(len - str.length)).join(' ');
}

function time(fn) {
var start = Number(new Date);
fn();
return (Number(new Date) - start) / 1000;
}

benchmark = function(label, fn) {
var duration = time(function() {
for (var i = 0; i < currentSuite.times; ++i) {
fn();
}
}).toFixed(3);
print(pad(' ' + label, 50 - String(duration).length) + duration + ' |');
};

suite = function(label, times, fn) {
currentSuite = this;
this.times = times;
print('\n ' + pad(label, 42 - String(this.times).length) + this.times + ' time(s)');
print(' -------------------------------------------------');
fn();
};
}());
</script>
</head>
<body>
<pre id="log">Running tests...</pre>

<script>
(function() {
var msgs = '';
var log = document.getElementById('log');

print = function(msg) {
msgs += msg + '\n';
};

print.commit = function() {
log.innerHTML = msgs;
};
}());

suite('Constructor', 1e4, function() {
var pattern = '^([.])\\1+$';

benchmark('XRegExp() + pattern cache flush', function() {
XRegExp(pattern, 'g');
XRegExp.cache.flush('patterns');
});

benchmark('XRegExp()', function() {
XRegExp(pattern, 'g');
});

benchmark('XRegExp.cache()', function() {
XRegExp.cache(pattern, 'g');
});

benchmark('RegExp()', function() {
new RegExp(pattern, 'g');
});
});

suite('exec', 1e4, function() {
var regexG = /(\b(?=x).(?=x).()??\2)+/g;
var str = Array(50 + 1).join('hello x world') + ' xx!';
var strs = [];
var pos = 5;

XRegExp.install('natives');
var fixedExec = RegExp.prototype.exec;
XRegExp.uninstall('natives');

// Generate all-different strings so Opera can't cheat with its regex/string match cache
for (var i = 0; i < 1e4; ++i) {
strs.push(str + i);
}

i = 0;
benchmark('Native RegExp::exec()', function() {
regexG.lastIndex = pos;
var match = regexG.exec(strs[i++]);
});

i = 0;
benchmark('Shimmed RegExp::exec()', function() {
regexG.lastIndex = pos;
var match = fixedExec.call(regexG, strs[i++]);
});

i = 0;
benchmark('XRegExp.exec()', function() {
var match = XRegExp.exec(strs[i++], regexG, pos);
});

i = 0;
benchmark('Native RegExp::exec() + sticky', function() {
regexG.lastIndex = pos;
var match = regexG.exec(strs[i++]);
if (match && match.index !== pos) {
match = null;
}
});

i = 0;
benchmark('Shimmed RegExp::exec() + sticky', function() {
regexG.lastIndex = pos;
var match = fixedExec.call(regexG, strs[i++]);
if (match && match.index !== pos) {
match = null;
}
});

i = 0;
// This should be the fastest in any browser that natively supports flag y
benchmark('XRegExp.exec() + sticky', function() {
var match = XRegExp.exec(strs[i++], regexG, pos, 'sticky');
});
});

print.commit();
</script>
</body>
</html>
7 changes: 3 additions & 4 deletions xregexp-all.js
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -458,11 +458,10 @@ var XRegExp = (function(undefined) {
return ''; return '';
}); });


// Throw on unknown native or nonnative flags
for (i = 0; i < flags.length; ++i) { for (i = 0; i < flags.length; ++i) {
chr = flags.charAt(i); if (!registeredFlags[flags.charAt(i)]) {
// Throw on unknown native or nonnative flags throw new SyntaxError(ERR_UNKNOWN_FLAG + flags.charAt(i));
if (!registeredFlags[chr]) {
throw new SyntaxError(ERR_UNKNOWN_FLAG + chr);
} }
} }


Expand Down

0 comments on commit 34d5d50

Please sign in to comment.