Skip to content
Browse files

add some basic perf tests

  • Loading branch information...
1 parent ab2cd6a commit 34d5d5008e628fb2e87c17a2d6a4696fa0ad3d0a @slevithan committed Aug 14, 2012
Showing with 158 additions and 10 deletions.
  1. +2 −2 README.md
  2. +3 −4 src/xregexp.js
  3. +150 −0 tests/perf.html
  4. +3 −4 xregexp-all.js
View
4 README.md
@@ -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 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
-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
View
7 src/xregexp.js
@@ -431,11 +431,10 @@ var XRegExp = (function(undefined) {
return '';
});
+ // Throw on unknown native or nonnative flags
for (i = 0; i < flags.length; ++i) {
- chr = flags.charAt(i);
- // Throw on unknown native or nonnative flags
- if (!registeredFlags[chr]) {
- throw new SyntaxError(ERR_UNKNOWN_FLAG + chr);
+ if (!registeredFlags[flags.charAt(i)]) {
+ throw new SyntaxError(ERR_UNKNOWN_FLAG + flags.charAt(i));
}
}
View
150 tests/perf.html
@@ -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>
View
7 xregexp-all.js
@@ -458,11 +458,10 @@ var XRegExp = (function(undefined) {
return '';
});
+ // Throw on unknown native or nonnative flags
for (i = 0; i < flags.length; ++i) {
- chr = flags.charAt(i);
- // Throw on unknown native or nonnative flags
- if (!registeredFlags[chr]) {
- throw new SyntaxError(ERR_UNKNOWN_FLAG + chr);
+ if (!registeredFlags[flags.charAt(i)]) {
+ throw new SyntaxError(ERR_UNKNOWN_FLAG + flags.charAt(i));
}
}

0 comments on commit 34d5d50

Please sign in to comment.
Something went wrong with that request. Please try again.