Created
February 17, 2012 22:49
-
-
Save papandreou/1855943 to your computer and use it in GitHub Desktop.
Benchmark of different ways of matching /@(-(?:[a-z]+-)+)?keyframes/ against a specific position in a string
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var testCases = [ | |
{ | |
input: new Array(4001).join('0123456789') + '@-webkit-keyframes {}' + new Array(4096).join('0123456789'), | |
idx: 40000 | |
}, | |
{ | |
input: new Array(4001).join('0123456789') + '@keyframes {}' + new Array(4096).join('0123456789'), | |
idx: 40000 | |
}, | |
{ | |
input: new Array(4001).join('0123456789') + '@invalid' + new Array(4001).join('0123456789') + '@keyframes{}', | |
idx: 40000 | |
} | |
]; | |
var atKeyframesRegExp = /@(-(?:[a-z]+-)+)?keyframes/g, | |
atKeyframesAtStartRegExp = /^@(-(?:[a-z]+-)+)?keyframes/; | |
exports.compare = { | |
'lastIndex + regExp.exec()': function () { | |
testCases.forEach(function (testCase) { | |
atKeyframesRegExp.lastIndex = testCase.idx; | |
var matchKeyframes = atKeyframesRegExp.exec(testCase.input); | |
if (matchKeyframes && matchKeyframes.index === testCase.idx) { | |
// Match! vendorPrefix === matchKeyframes[1] | |
} | |
}); | |
}, | |
'substring().match()': function () { | |
testCases.forEach(function (testCase) { | |
var matchKeyframes = atKeyframesAtStartRegExp.exec(testCase.input.substring(testCase.idx)); | |
if (matchKeyframes) { | |
// Match! vendorPrefix = matchKeyframes[1] | |
} | |
}); | |
}, | |
'low-level string gymnastics': function () { | |
testCases.forEach(function (testCase) { | |
var input = testCase.input; | |
if (input.substring(testCase.idx, testCase.idx + '@keyframes'.length) === '@keyframes') { | |
// Match! vendorPrefix = undefined | |
} else { | |
var j = testCase.idx + 1, | |
state = 0, | |
accept = false; | |
OUTER: while (j < testCase.input.length) { | |
var ch = input[j]; | |
switch (state) { | |
case 0: | |
if (ch === '-') { | |
state = 1; | |
break; | |
} else { | |
break OUTER; | |
} | |
case 1: | |
if (ch >= 'a' && ch <= 'z') { | |
state = 2; | |
break; | |
} else { | |
break OUTER; | |
} | |
case 2: | |
if (ch >= 'a' && ch <= 'z') { | |
// Stay in state 2 | |
break; | |
} else if (ch === '-') { | |
state = 3; | |
break; | |
} else { | |
break OUTER; | |
} | |
case 3: | |
if (ch === 'k') { | |
state = 4; | |
break; | |
} else if (ch >= 'a' && ch <= 'z') { | |
state = 2; | |
break; | |
} else { | |
break OUTER; | |
} | |
case 4: | |
if (ch === 'e') { | |
state = 5; | |
break; | |
} else if (ch >= 'a' && ch <= 'z') { | |
state = 2; | |
break; | |
} else { | |
break OUTER; | |
} | |
case 5: | |
if (ch === 'y') { | |
state = 6; | |
break; | |
} else if (ch >= 'a' && ch <= 'z') { | |
state = 2; | |
break; | |
} else { | |
break OUTER; | |
} | |
case 6: | |
if (ch === 'f') { | |
state = 7; | |
break; | |
} else if (ch >= 'a' && ch <= 'z') { | |
state = 2; | |
break; | |
} else { | |
break OUTER; | |
} | |
case 7: | |
if (ch === 'r') { | |
state = 8; | |
break; | |
} else if (ch >= 'a' && ch <= 'z') { | |
state = 2; | |
break; | |
} else { | |
break OUTER; | |
} | |
case 8: | |
if (ch === 'a') { | |
state = 9; | |
break; | |
} else if (ch >= 'a' && ch <= 'z') { | |
state = 2; | |
break; | |
} else { | |
break OUTER; | |
} | |
case 9: | |
if (ch === 'm') { | |
state = 10; | |
break; | |
} else if (ch >= 'a' && ch <= 'z') { | |
state = 2; | |
break; | |
} else { | |
break OUTER; | |
} | |
case 10: | |
if (ch === 'e') { | |
state = 11; | |
break; | |
} else if (ch >= 'a' && ch <= 'z') { | |
state = 2; | |
break; | |
} else { | |
break OUTER; | |
} | |
case 11: | |
if (ch === 's') { | |
accept = true; | |
break OUTER; | |
} else if (ch >= 'a' && ch <= 'z') { | |
state = 2; | |
break; | |
} else { | |
break OUTER; | |
} | |
} | |
j += 1; | |
} | |
var vendorPrefix; | |
if (accept) { | |
// Match! vendorPrefix = testCase.input.substring(testCase.idx + 1, 1 + j - 'keyframes'.length); | |
} | |
} | |
}); | |
} | |
}; | |
require('bench').runMain(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
benchmarking /home/andreas/work/gist-1855943/bench.js | |
Please be patient. | |
{ node: '0.4.13-pre', | |
v8: '3.1.8.27', | |
ares: '1.7.4', | |
ev: '4.4', | |
openssl: '0.9.8o' } | |
Scores: (bigger is better) | |
low-level string gymnastics | |
Raw: | |
> 998.001998001998 | |
> 989.010989010989 | |
> 1013.986013986014 | |
> 999.000999000999 | |
> 1025.974025974026 | |
Average (mean) 1005.1948051948053 | |
substring().match() | |
Raw: | |
> 41.62537165510406 | |
> 40.553907022749755 | |
> 40.75546719681908 | |
> 42.03323558162268 | |
> 40.0390625 | |
Average (mean) 41.00140879125912 | |
lastIndex + regExp.exec() | |
Raw: | |
> 22.30843840931135 | |
> 22.660098522167488 | |
> 22.660098522167488 | |
> 22.22222222222222 | |
> 22.373540856031127 | |
Average (mean) 22.444879706379936 | |
Winner: low-level string gymnastics | |
Compared with next highest (substring().match()), it's: | |
95.92% faster | |
24.52 times as fast | |
1.39 order(s) of magnitude faster | |
Compared with the slowest (lastIndex + regExp.exec()), it's: | |
97.77% faster | |
44.79 times as fast | |
1.65 order(s) of magnitude faster | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
benchmarking /home/andreas/work/gist-1855943/bench.js | |
Please be patient. | |
{ node: '0.4.13-pre', | |
v8: '3.1.8.27', | |
ares: '1.7.4', | |
ev: '4.4', | |
openssl: '0.9.8o' } | |
Scores: (bigger is better) | |
lastIndex + regExp.exec() | |
Raw: | |
> 2060.939060939061 | |
> 1980.01998001998 | |
> 1966.033966033966 | |
> 1926.073926073926 | |
> 2102.8971028971027 | |
Average (mean) 2007.1928071928073 | |
low-level string gymnastics | |
Raw: | |
> 1171.828171828172 | |
> 1167.832167832168 | |
> 1195.8041958041958 | |
> 1219.7802197802198 | |
> 1170.8291708291708 | |
Average (mean) 1185.2147852147853 | |
substring().match() | |
Raw: | |
> 55.50049554013875 | |
> 55.61072492552135 | |
> 54.509415262636274 | |
> 54.78087649402391 | |
> 54.40158259149357 | |
Average (mean) 54.96061896276277 | |
Winner: lastIndex + regExp.exec() | |
Compared with next highest (low-level string gymnastics), it's: | |
40.95% faster | |
1.69 times as fast | |
0.23 order(s) of magnitude faster | |
Compared with the slowest (substring().match()), it's: | |
97.26% faster | |
36.52 times as fast | |
1.56 order(s) of magnitude faster | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment