Tweaks to rnocache
JavaScript performance comparison
Info
Jquery uses the rnocache regex for determining problematic html tags for both caching and for the use of innerHtml. The problem is that these two purposes share very little overlap, and conflating them results in not using innerHtml in places where it's perfectly safe, and much faster.
For discussion and bug see:
- http://bugs.jquery.com/ticket/6782
- http://forum.jquery.com/topic/html-performance-vs-cruft
- http://forum.jquery.com/topic/option-tag-is-considered-a-non-cache-element
To implement the test, I extend jquery with a .html2() function which is a direct copy of the 1.5.1 version of .html(), but add a new regex test:
rnoInnerhtml = /<script|<style/i
which I use in place of rnocache within the .html. This change allows me to then copy a select box using innerHTML rather than .empty().append() which results in some rather large speed increases.
Preparation code
<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<div>Original: <div id="source"><select id="test_select" name="test_select">
<option label="1">0</option>
<option label="1">1</option>
<option label="2">2</option>
<option label="3" selected="selected">3</option>
<option label="4">4</option>
<option label="1">5</option>
<option label="2">6</option>
<option label="3">7</option>
<option label="4">8</option>
<option label="1">9</option>
</select>
</div></div>
Following two selects should be identical:
<div>Unoptimized copy: <div id="destination"></div></div>
<div>Optimized copy:<div id="destination2"></div></div>
<script>
var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
rleadingWhitespace = /^\s+/,
rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
rtagName = /<([\w:]+)/,
rtbody = /<tbody/i,
rhtml = /<|&#?\w+;/,
rnoInnerhtml = /<script|<style/i,
rnocache = /<(?:script|object|embed|option|style)/i,
// checked="checked" or checked (html5)
rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
wrapMap = {
option: [1, "<select multiple='multiple'>", "</select>"],
legend: [1, "<fieldset>", "</fieldset>"],
thead: [1, "<table>", "</table>"],
tr: [2, "<table><tbody>", "</tbody></table>"],
td: [3, "<table><tbody><tr>", "</tr></tbody></table>"],
col: [2, "<table><tbody></tbody><colgroup>", "</colgroup></table>"],
area: [1, "<map>", "</map>"],
_default: [0, "", ""]
};
wrapMap.optgroup = wrapMap.option;
wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
wrapMap.th = wrapMap.td;
// IE can't serialize <link> and <script> tags normally
if (!jQuery.support.htmlSerialize) {
wrapMap._default = [1, "div<div>", "</div>"];
}
jQuery.fn.extend({
html2: function(value) {
if (value === undefined) {
return this[0] && this[0].nodeType === 1 ? this[0].innerHTML.replace(rinlinejQuery, "") : null;
// See if we can take a shortcut and just use innerHTML
} else if (typeof value === "string" && !rnoInnerhtml.test(value) && (jQuery.support.leadingWhitespace || !rleadingWhitespace.test(value)) && !wrapMap[(rtagName.exec(value) || ["", ""])[1].toLowerCase()]) {
value = value.replace(rxhtmlTag, "<$1></$2>");
try {
for (var i = 0, l = this.length; i < l; i++) {
// Remove element nodes and prevent memory leaks
if (this[i].nodeType === 1) {
jQuery.cleanData(this[i].getElementsByTagName("*"));
this[i].innerHTML = value;
}
}
// If using innerHTML throws an exception, use the fallback method
} catch (e) {
this.empty().append(value);
}
} else if (jQuery.isFunction(value)) {
this.each(function(i) {
var self = jQuery(this);
self.html(value.call(this, i, self.html()));
});
} else {
this.empty().append(value);
}
return this;
}
});
var template = $("#source").html();
</script>
Preparation code output
Test runner
Warning! For accurate results, please disable Firebug before running the tests. (Why?)
Java applet disabled.
| Test | Ops/sec | |
|---|---|---|
using standard nocache |
|
pending… |
using innerHTML optimized regex |
|
pending… |
Compare results of other browsers
Revisions
You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:
- Revision 1: published by Charles McNulty and last updated
- Revision 7: published by Charles McNulty
- Revision 8: published by Charlie
- Revision 9: published by Charlie
0 comments