-
-
Save katyo/4c7c469c28b5976e16ca87d89bac382a to your computer and use it in GitHub Desktop.
var allAttrs = ["abbr","accept","accept-charset","accesskey","action","alt","async","autocomplete","autocomplete","autofocus","autoplay","border","challenge","charset","charset","checked","cite","class","cols","colspan","content","contenteditable","controls","coords","crossorigin","data","datetime","datetime","default","defer","dir","dir","dirname","disabled","download","enctype","for","for","form","formaction","formenctype","formmethod","formnovalidate","formtarget","headers","height","hidden","high","href","href","href","hreflang","http-equiv","id","ismap","keytype","kind","label","lang","list","loop","low","manifest","max","max","maxlength","media","mediagroup","method","min","min","minlength","multiple","muted","name","name","name","name","name","name","novalidate","optimum","pattern","placeholder","poster","preload","readonly","rel","required","reversed","rows","rowspan","sandbox","spellcheck","scope","selected","shape","size","sizes","span","src","srcdoc","srclang","start","step","style","tabindex","target","target","target","title","title","title","title","title","translate","type","type","type","type","type","typemustmatch","usemap","value","value","value","value","value","value","width","wrap"]; | |
var booleanAttrsArray = ["allowfullscreen", "async", "autofocus", "autoplay", "checked", "compact", "controls", "declare", "default", "defaultchecked", "defaultmuted", "defaultselected", "defer", "disabled", "draggable", "enabled", "formnovalidate", "hidden", "indeterminate", "inert", "ismap", "itemscope", "loop", "multiple", "muted", "nohref", "noresize", "noshade", "novalidate", "nowrap", "open", "pauseonexit", "readonly", "required", "reversed", "scoped", "seamless", "selected", "sortable", "spellcheck", "translate", "truespeed", "typemustmatch", "visible"]; | |
var booleanAttrsHash = { | |
allowfullscreen: 1, | |
async: 1, | |
autofocus: 1, | |
autoplay: 1, | |
checked: 1, | |
compact: 1, | |
controls: 1, | |
declare: 1, | |
default: 1, | |
defaultchecked: 1, | |
defaultmuted: 1, | |
defaultselected: 1, | |
defer: 1, | |
disabled: 1, | |
draggable: 1, | |
enabled: 1, | |
formnovalidate: 1, | |
hidden: 1, | |
indeterminate: 1, | |
inert: 1, | |
ismap: 1, | |
itemscope: 1, | |
loop: 1, | |
multiple: 1, | |
muted: 1, | |
nohref: 1, | |
noresize: 1, | |
noshade: 1, | |
novalidate: 1, | |
nowrap: 1, | |
open: 1, | |
pauseonexit: 1, | |
readonly: 1, | |
required: 1, | |
reversed: 1, | |
scoped: 1, | |
seamless: 1, | |
selected: 1, | |
sortable: 1, | |
spellcheck: 1, | |
translate: 1, | |
truespeed: 1, | |
typemustmatch: 1, | |
visible: 1 | |
}; | |
var booleanAttrsRegex = /^(?:a(?:llowfullscreen|sync|uto(?:focus|play))|c(?:hecked|o(?:mpact|ntrols))|d(?:e(?:clare|f(?:ault(?:(?:check|(?:mu|selec)t)ed)?|er))|isabled|raggable)|enabled|formnovalidate|hidden|i(?:n(?:determinate|ert)|smap|temscope)|loop|mu(?:ltiple|ted)|no(?:href|resize|shade|validate|wrap)|open|pauseonexit|re(?:adonly|(?:quir|vers)ed)|s(?:coped|e(?:amless|lected)|ortable|pellcheck)|t(?:r(?:anslate|uespeed)|ypemustmatch)|visible)$/; | |
var booleanAttrsSet = new Set(booleanAttrsArray); | |
var n = 10e3; | |
function bench(t, f) { | |
var s = Date.now(); | |
for (var i = 0; i < n; i++) { | |
f(); | |
} | |
var e = Date.now() - s; | |
console.log(t, (n/1000) + "k", e, "mS"); | |
} | |
bench("impelling", function() { | |
var res; | |
for(var i = 0; i < allAttrs.length; i++) { | |
res = allAttrs.indexOf(allAttrs[i]); | |
} | |
}); | |
bench("array search", function() { | |
var res; | |
for(var i = 0; i < allAttrs.length; i++) { | |
res = booleanAttrsArray.indexOf(allAttrs[i]); | |
} | |
}); | |
bench("hash lookup", function() { | |
var res; | |
for(var i = 0; i < allAttrs.length; i++) { | |
res = booleanAttrsHash[allAttrs[i]]; | |
} | |
}); | |
bench("regex match", function() { | |
var res; | |
for(var i = 0; i < allAttrs.length; i++) { | |
res = booleanAttrsRegex.test(allAttrs[i]); | |
} | |
}); | |
bench("set lookup", function() { | |
var res; | |
for(var i = 0; i < allAttrs.length; i++) { | |
res = booleanAttrsSet.has(allAttrs[i]); | |
} | |
}); |
How is a regex faster than a hash lookup? 🤔
And, what about the bundle size? Does it increase / decrease?
It may looks surprising, but testing string using regex really faster than hash(?)/array lookup. At least all mainstream JS engines, which I tested, confirm this. But real increasing of speed is differs from engine to engine. Look at my results above or you can run test code yourself.
ECMAScript Environment | Speed increase comparing with hash lookup |
---|---|
Firefox: 45.6.0 | 15% |
Chromium: 55.0.2883.75 | 56% |
Node: v4.3.1 | 80% |
Of course, the bundle size also decrease when we use regex. It's so because regex is short itself, but optimized regex is yet more short than array with strings or object with keys.
@nunocastromartins: I added test using Set too. The sets works really much faster in v8-based environments (Node, Chromium).
Finding a real use case for something less commonly used it exciting.
Finding a techniques for optimization of hot code path is exciting.
This is quite interesting.
Just out of curiosity, could you add a test using
Set
?