<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Flagrant Badassery &#187; Performance</title>
	<atom:link href="http://blog.stevenlevithan.com/category/performance/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.stevenlevithan.com</link>
	<description>A JavaScript and regular expression centric blog</description>
	<pubDate>Sat, 09 Aug 2008 15:09:54 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6</generator>
	<language>en</language>
			<item>
		<title>Timed Memoization</title>
		<link>http://blog.stevenlevithan.com/archives/timed-memoization</link>
		<comments>http://blog.stevenlevithan.com/archives/timed-memoization#comments</comments>
		<pubDate>Sun, 06 Jan 2008 17:56:33 +0000</pubDate>
		<dc:creator>Steven Levithan</dc:creator>
		
		<category><![CDATA[JavaScript]]></category>

		<category><![CDATA[Performance]]></category>

		<category><![CDATA[memoization]]></category>

		<guid isPermaLink="false">http://blog.stevenlevithan.com/archives/timed-memoization</guid>
		<description><![CDATA[Certain operations are computationally expensive, but because their results might change over time or due to outside influences, they don't lend themselves to typical memoization &#8212; take for example getElementsByClassName. Here's a JavaScript timed memoization decorator / higher-order-function I made to help with these cases, which accepts an optional expiration argument in milliseconds.

function memoize (functor, [...]]]></description>
			<content:encoded><![CDATA[<p>Certain operations are computationally expensive, but because their results might change over time or due to outside influences, they don't lend themselves to typical <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a> &mdash; take for example <code>getElementsByClassName</code>. Here's a JavaScript timed memoization decorator / higher-order-function I made to help with these cases, which accepts an optional expiration argument in milliseconds.</p>

<pre class="code">function memoize (functor, expiration) {
	var memo = {};
	return function () {
		var key = Array.prototype.join.call(arguments, "§");
		if (key in memo)
			return memo[key];
		if (expiration)
			setTimeout(function () {delete memo[key];}, expiration);
		return memo[key] = functor.apply(this, arguments);
	};
}
</pre>

<p>This approach allows you to turn any function into a memoizing function. Note that return values are memoized for each set of arguments. However, due to technical constraints it's only reliable when the arguments are arrays or scalar values, but you could easily use e.g. a <code>toJSON</code> method rather than <code>join</code> to serialize objects as part of the cache key (at some additional overhead cost).</p>

<p>You can use the above code like this:</p>

<pre class="code"><span class="comment">// Make a function which memoizes for 1000 milliseconds at a time</span>
var fn = memoize(function () {
	Array(500000).join("."); <span class="comment">// slow</span>
	return true;
}, 1000);
</pre>

<p>&hellip;Or leave out the expiration argument to permanently memoize.</p>

<p>Here are a couple more posts on JavaScript memoization:</p>

<ul>
	<li><a href="http://osteele.com/archives/2006/04/javascript-memoization">One-Line JavaScript Memoization</a> by Oliver Steele</li>
	<li><a href="http://talideon.com/weblog/2005/07/javascript-memoization.cfm">Memoization in JavaScript</a> by Keith Gaughan</li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://blog.stevenlevithan.com/archives/timed-memoization/feed</wfw:commentRss>
		</item>
		<item>
		<title>Performance of Greedy vs. Lazy Regex Quantifiers</title>
		<link>http://blog.stevenlevithan.com/archives/greedy-lazy-performance</link>
		<comments>http://blog.stevenlevithan.com/archives/greedy-lazy-performance#comments</comments>
		<pubDate>Sat, 01 Dec 2007 18:04:43 +0000</pubDate>
		<dc:creator>Steven Levithan</dc:creator>
		
		<category><![CDATA[Performance]]></category>

		<category><![CDATA[Regular Expressions]]></category>

		<category><![CDATA[regex performance]]></category>

		<guid isPermaLink="false">http://blog.stevenlevithan.com/archives/greedy-lazy-performance</guid>
		<description><![CDATA[A common misconception about regular expression performance is that lazy quantifiers (also called non-greedy, reluctant, minimal, or ungreedy) are faster than their greedy equivalents. That's generally not true, but with an important qualifier: in practice, lazy quantifiers often are faster. This seeming contradiction is due to the fact that many people rely on backtracking to [...]]]></description>
			<content:encoded><![CDATA[<p>A common misconception about regular expression performance is that lazy quantifiers (also called non-greedy, reluctant, minimal, or ungreedy) are faster than their greedy equivalents. That's generally not true, but with an important qualifier: in <em>practice</em>, lazy quantifiers often <em>are</em> faster. This seeming contradiction is due to the fact that many people rely on backtracking to compensate for the impreciseness of their patterns, often without realizing this is what they're doing. Hence, the previously mentioned misconception stems from that fact that lazy quantifiers often result in much less backtracking when combined with long subject strings and the (mis)use of overly flexible regex tokens such as the dot.</p>

<p>Consider the following simple example: When the regexes <code class="regex">&lt;<b>.*?</b>&gt;</code> and <code class="regex">&lt;<i>[^&gt;]</i><b>*</b>&gt;</code> are applied to the subject string "&lt;0123456789&gt;", they are functionally equivalent. The only difference is how the regex engine goes about generating the match. However, the latter regex (which uses a greedy quantifier) is more efficient, because it describes what the user really means: match the character "&lt;", followed by any number of characters which are not "&gt;", and finally, match the character "&gt;". Defined this way, it requires no backtracking in the case of any successful match, and only one backtracking step in the case of any unsuccessful match. Hand-optimization of regex patterns largely revolves around the ideas of reducing backtracking and the steps which are potentially required to match or fail at any given character position, and here we've reduced both cases to the absolute minimum.</p>

<p>So what exactly is different about how a backtracking, leftmost-first regex engine (your traditional NFA engine type, which describes most modern, Perl-derivative flavors) goes about matching our subject text when working with these two regexes? Let's first take a look at what happens with <code class="regex">&lt;<b>.*?</b>&gt;</code>. I'll use the <a href="http://www.regexbuddy.com/cgi-bin/affref.pl?aff=SteveL">RegexBuddy</a> debugger style to illustrate each step.</p>

<style type="text/css">
	.regexDebug li {font-size:100%; font-family:"Courier New", Courier, monospace; line-height:100%; margin-top:0 !important; margin-bottom:0 !important;}
	.regexDebug span.msg {background:#f04000; color:#fff;}
	.regexDebug span.odd {background:#80c0ff;}
	.regexDebug span.even {background:#68a0c0;}
	.regexDebug span.at {text-decoration:underline;}
</style>

<p class="stealth">Note: If you're reading this in a feed reader or aggregator which strips out inline styles, see the <a href="http://blog.stevenlevithan.com/archives/greedy-lazy-performance"><strong>original post</strong></a>, which should make things much easier to follow.</p>

<ol class="regexDebug">
	<li>Beginning match attempt at character 0</li>
	<li><span class="odd">&lt;</span></li>
	<li><span class="odd">&lt;</span><span class="msg">ok</span></li>
	<li><span class="odd">&lt;</span><span class="msg">backtrack</span></li>
	<li><span class="odd">&lt;</span><span class="even">0</span></li>
	<li><span class="odd">&lt;</span><span class="even">0</span><span class="msg">backtrack</span></li>
	<li><span class="odd">&lt;</span><span class="even">0<span class="at">1</span></span></li>
	<li><span class="odd">&lt;</span><span class="even">0<span class="at">1</span></span><span class="msg">backtrack</span></li>
	<li><span class="odd">&lt;</span><span class="even">01<span class="at">2</span></span></li>
	<li><span class="odd">&lt;</span><span class="even">01<span class="at">2</span></span><span class="msg">backtrack</span></li>
	<li><span class="odd">&lt;</span><span class="even">012<span class="at">3</span></span></li>
	<li><span class="odd">&lt;</span><span class="even">012<span class="at">3</span></span><span class="msg">backtrack</span></li>
	<li><span class="odd">&lt;</span><span class="even">0123<span class="at">4</span></span></li>
	<li><span class="odd">&lt;</span><span class="even">0123<span class="at">4</span></span><span class="msg">backtrack</span></li>
	<li><span class="odd">&lt;</span><span class="even">01234<span class="at">5</span></span></li>
	<li><span class="odd">&lt;</span><span class="even">01234<span class="at">5</span></span><span class="msg">backtrack</span></li>
	<li><span class="odd">&lt;</span><span class="even">012345<span class="at">6</span></span></li>
	<li><span class="odd">&lt;</span><span class="even">012345<span class="at">6</span></span><span class="msg">backtrack</span></li>
	<li><span class="odd">&lt;</span><span class="even">0123456<span class="at">7</span></span></li>
	<li><span class="odd">&lt;</span><span class="even">0123456<span class="at">7</span></span><span class="msg">backtrack</span></li>
	<li><span class="odd">&lt;</span><span class="even">01234567<span class="at">8</span></span></li>
	<li><span class="odd">&lt;</span><span class="even">01234567<span class="at">8</span></span><span class="msg">backtrack</span></li>
	<li><span class="odd">&lt;</span><span class="even">012345678<span class="at">9</span></span></li>
	<li><span class="odd">&lt;</span><span class="even">012345678<span class="at">9</span></span><span class="odd">&gt;</span></li>
	<li><span class="msg">Match found</span></li>
</ol>

<p>The text <span class="regexDebug"><span class="msg">ok</span></span> means the engine completed a successful, zero-length match, and <span class="regexDebug"><span class="msg">backtrack</span></span> shows where the engine backtracks to the last choice point. As you can see here, with lazy quantification the engine backtracks <em>forward</em> after each character which is not followed by "&gt;".</p>

<p>Here's what happens with <code class="regex">&lt;<i>[^&gt;]</i><b>*</b>&gt;</code>:</p>

<ol class="regexDebug">
	<li>Beginning match attempt at character 0</li>
	<li><span class="odd">&lt;</span></li>
	<li><span class="odd">&lt;</span><span class="even">012345678<span class="at">9</span></span></li>
	<li><span class="odd">&lt;</span><span class="even">012345678<span class="at">9</span></span><span class="odd">&gt;</span></li>
	<li><span class="msg">Match found</span></li>
</ol>

<p>As you can see, 20 fewer steps are required, and there is no backtracking. This is faster, and can also increase the potential for internal optimization of the matching process. As a simple example, when greedily quantifying an any-character token, the engine can simply move the read-head to the end of the string, rather than testing every character along the way (this is an oversimplification of the process taken by modern regex engines, but you get the idea). You can see this exact kind of internal optimization occurring in IE with the "trim8" pattern in my <a href="http://blog.stevenlevithan.com/archives/faster-trim-javascript">Faster JavaScript Trim</a> post from a while back.</p>

<p>You might be wondering what happens if we use the regex <code class="regex">&lt;<b>.*</b>&gt;</code>. Take a look:</p>

<ol class="regexDebug">
	<li>Beginning match attempt at character 0</li>
	<li><span class="odd">&lt;</span></li>
	<li><span class="odd">&lt;</span><span class="even">0123456789<span class="at">&gt;</span></span></li>
	<li><span class="odd">&lt;</span><span class="even">0123456789<span class="at">&gt;</span></span><span class="msg">backtrack</span></li>
	<li><span class="odd">&lt;</span><span class="even">012345678<span class="at">9</span></span></li>
	<li><span class="odd">&lt;</span><span class="even">012345678<span class="at">9</span></span><span class="odd">&gt;</span></li>
	<li><span class="msg">Match found</span></li>
</ol>

<p>Although the output didn't change much when used with our subject string of "&lt;0123456789&gt;", you can see that the <code class="regex"><b>.*</b></code> caused the engine to trek all the way to the end of the string, then backtrack from the right. If we'd used a 10,000-character string without newlines or other "&gt;" characters, that would've resulted in nearly 10,000 backtracks.</p>

<p>In short:</p>

<ul>
	<li>Be careful about using the more appropriate type of quantification (to your best approximation, since this often depends on the subject string) even when it has no impact on the text matched by your regex.</li>
	<li>Try to make your patterns as explicit as possible, to better guide the regex engine and avoid backtracking.</li>
	<li>If possible, avoid greedy quantification of the dot and other needlessly flexible tokens.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.stevenlevithan.com/archives/greedy-lazy-performance/feed</wfw:commentRss>
		</item>
		<item>
		<title>JavaScript String Multiplication Performance Exploration</title>
		<link>http://blog.stevenlevithan.com/archives/fast-string-multiply</link>
		<comments>http://blog.stevenlevithan.com/archives/fast-string-multiply#comments</comments>
		<pubDate>Sun, 18 Nov 2007 07:56:43 +0000</pubDate>
		<dc:creator>Steven Levithan</dc:creator>
		
		<category><![CDATA[Code Challenge]]></category>

		<category><![CDATA[JavaScript]]></category>

		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://blog.stevenlevithan.com/archives/fast-string-multiply</guid>
		<description><![CDATA[Since JavaScript concatenates strings with the + operator, it would be nifty if it would also let you multiply strings using e.g. str * 10 (as can be done in Python, at least). Since you can't do that, and no native string multiplication method is provided, I recently explored a few ways to pull it [...]]]></description>
			<content:encoded><![CDATA[<p>Since JavaScript concatenates strings with the <code>+</code> operator, it would be nifty if it would also let you multiply strings using e.g. <code>str * 10</code> (as can be done in Python, at least). Since you can't do that, and no native string multiplication method is provided, I recently explored a few ways to pull it off&hellip;</p>

<p>A naïve approach to writing a string multiplier function goes something like this:</p>

<pre class="code">function mul0 (str, num) {
	if (!num) return "";
	var newStr = str;
	while (--num) newStr += str;
	return newStr;
}
</pre>

<p>As many JavaScripters are aware, that isn't the best approach since string concatenation can be quite slow in Internet Explorer. And while IE tends to get a bad rap for this (fortunately, the IE team is <a href="http://blogs.msdn.com/jscript/archive/2007/10/17/performance-issues-with-string-concatenation-in-jscript.aspx">fixing the problem</a> in the next version of their browser), Firefox isn't exactly blazing fast at string concatenation either. Due to the performance issues, the typical string multiplication approach is to build an array and <code>join</code> it. Here's a nice, short way to do that:</p>

<pre class="code">function mul1 (str, num) {
	return num ? Array(num + 1).join(str) : "";
}
</pre>

<p>Note that the falsy <code>num</code> handling is probably not warranted in this case since the function would handle value <code>0</code> correctly without it. It's done anyway to keep functionality equivalent across the variations.</p>

<p>Unfortunately, <code>mul1</code> can still be pretty slow in Firefox 2 when multiplying large strings many times. It might be unnoticeable with small strings and repetition numbers, but the completion time goes up at a super-linear rate as the numbers increase. In search of a faster solution, I tried using a regex to keep down the size of the string being worked with:</p>

<pre class="code">var mul2 = function () {
	function mul (str, num) {
		return Array(num + 1).join(str);
	}
	return function (str, num) {
		return num ? str.replace(/^/, mul("$'", num - 1)) : "";
	};
}();
</pre>

<p>The above multiplies the two-character string "<code>$'</code>" <code>num - 1</code> times, then uses that as the replacement for a regex which just matches the start of the string (<code>$'</code> returns the text to the right of the match). How does that perform? It delivers in Firefox 2 on my Windows Vista system, with numbers like 95ms vs. 29800ms (<code>mul1</code>) when using a 2700x2700 string length/multiplier. However, based on my testing, that sort of speed gain appears to be limited to Firefox, and in Safari 3 beta <code>mul2</code> is considerably slower that the alternative versions.</p>

<p>Finally, I tried creating a version which multiplied the string at an exponential rate:</p>

<pre class="code">function mul3 (str, num) {
	if (!num) return "";
	var	orig = str,
		soFar = [str],
		added = 1,
		left, i;
	while (added &lt; num) {
		left = num - added;
		str = orig;
		for (i = 2; i &lt; left; i *= 2) {
			str += str;
		}
		soFar.push(str);
		added += (i / 2);
	}
	return soFar.join("");
}
</pre>

<p>Although that might be more code than you're willing to dedicate to a string multiplication method, it's the fastest of the above versions on average cross-browser. I've also tried a few variations using from zero to two arrays and various array methods (<code>push</code>, <code>concat</code>, etc.), but the above seems to be the fastest on average across the big four browsers.</p>

<p>Make sure to <a href="http://stevenlevithan.com/demo/mul/test.html">try the tests for yourself</a>, and let me know your thoughts and how you would improve the code.</p>

<hr/>

<p><strong>Edit:</strong> <a href="http://cixar.com/~kris.kowal/">Kris Kowal</a> contributed <code>mul4</code> (shown below, and added to the test page). It uses binary interpolation, and in Kris's words "it takes advantage of a fun bitwise identity: <code>(1 &lt;&lt; n) == Math.pow(2, n)</code>". On my system it's significantly faster than <code>mul3</code> in Firefox, but a little slower than <code>mul3</code> in IE, Safari, and Opera. Due to its high speed and lighter weight, this looks like the one to beat. Try the <a href="http://stevenlevithan.com/demo/mul/test.html">test page</a> in several browsers and see what you think.</p>

<pre class="code">function mul4 (str, num) {
	var acc = [];
	for (var i = 0; (1 &lt;&lt; i) &lt;= num; i++) {
		if ((1 &lt;&lt; i) &amp; num)
			acc.push(str);
		str += str;
	}
	return acc.join("");
}
</pre>

<hr/>

<p><strong>Edit 2:</strong> <a href="http://www.liucougar.net/blog">LiuCougar</a> of the Dojo development team posted a <a href="http://www.liucougar.net/blog/archives/76">follow-up</a> which includes several additional variations, and <a href="http://web-graphics.com/">David Andersson</a> emailed me an additional four variations including this one:</p>

<pre class="code">function mul8 (str, num) {
	var	i = Math.ceil(Math.log(num) / Math.LN2),
		res = str;
	do {
		res += res;
	} while (0 &lt; --i);
	return res.slice(0, str.length * num);
}
</pre>

<p>I should clarify however that this is mostly just academic discussion, since repeating the kinds of strings in the test page as many times as it does is a pretty crazy idea. Still, it's fun to experiment. <img src="http://blog.stevenlevithan.com/wp-includes/images/smilies/icon_smile.gif" alt="smile"/></p>

<hr/>

<p><strong>Edit 3:</strong> All the variations posted or emailed in response to this post can be seen at <strong style="font-size:120%"><a href="http://stevenlevithan.com/demo/mul/all.js">stevenlevithan.com/demo/mul/all.js</a></strong>. For the sake of consistency I've made a few minor adjustments to some of the functions such as whitespace tweaks and renaming the input arguments to <code>str</code> and <code>num</code>.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.stevenlevithan.com/archives/fast-string-multiply/feed</wfw:commentRss>
		</item>
		<item>
		<title>Regex Performance Optimization</title>
		<link>http://blog.stevenlevithan.com/archives/regex-optimization</link>
		<comments>http://blog.stevenlevithan.com/archives/regex-optimization#comments</comments>
		<pubDate>Thu, 04 Oct 2007 10:18:23 +0000</pubDate>
		<dc:creator>Steven Levithan</dc:creator>
		
		<category><![CDATA[Performance]]></category>

		<category><![CDATA[Regular Expressions]]></category>

		<category><![CDATA[regex performance]]></category>

		<guid isPermaLink="false">http://blog.stevenlevithan.com/archives/regex-optimization</guid>
		<description><![CDATA[Crafting efficient regular expressions is somewhat of an art. In large part, it centers around controlling/minimizing backtracking and the number of steps it takes the regex engine to match or fail, but the fact that most engines implement different sets of internal optimizations (which can either make certain operations faster, or avoid work by performing [...]]]></description>
			<content:encoded><![CDATA[<p>Crafting efficient regular expressions is somewhat of an art. In large part, it centers around controlling/minimizing backtracking and the number of steps it takes the regex engine to match or fail, but the fact that most engines implement different sets of internal optimizations (which can either make certain operations faster, or avoid work by performing simplified pre-checks or skipping unnecessary operations, etc.) also makes the topic dependent on the particular regex flavor and implementation you're using to a significant extent. Most developers aren't deeply aware of regex performance issues, so when they run into problems with regular expressions running slowly, their first thought is to remove the regexes. In reality, most non-trivial regexes I've seen could be significantly optimized for efficiency, and I've frequently seen <em>dramatic</em> improvements as a result of doing so.</p>

<p>The best discussion of regex optimization I've seen is chapter six (a good 60 pages) of <cite><a href="http://regex.info/">Mastering Regular Expressions</a>, Third Edition</cite> by <a href="http://regex.info/blog/">Jeffrey Friedl</a>. Unfortunately, other good material on the subject is fairly scarce, so I was pleasantly surprised to stumble upon the recent article <cite class="bold"><a href="http://www.javaworld.com/javaworld/jw-09-2007/jw-09-optimizingregex.html">Optimizing regular expressions in Java</a></cite> by Cristian Mocanu. Of course, it is in part Java specific, but for the most part it is a good article on the basics of optimization for traditional NFA regex engines. Check it out.</p>

<p>Have you seen any good articles or discussions about regular expression performance or efficiency optimization recently? Do you have any questions about the subject? Experience or pointers to share? Let me know. (I hope to eventually write up an in-depth article on JavaScript regex optimization, with lots of tips, techniques, and cross-browser benchmarks.)</p>]]></content:encoded>
			<wfw:commentRss>http://blog.stevenlevithan.com/archives/regex-optimization/feed</wfw:commentRss>
		</item>
		<item>
		<title>When innerHTML isn&#8217;t Fast Enough</title>
		<link>http://blog.stevenlevithan.com/archives/faster-than-innerhtml</link>
		<comments>http://blog.stevenlevithan.com/archives/faster-than-innerhtml#comments</comments>
		<pubDate>Wed, 12 Sep 2007 04:39:32 +0000</pubDate>
		<dc:creator>Steven Levithan</dc:creator>
		
		<category><![CDATA[Cross-Browser Issues]]></category>

		<category><![CDATA[JavaScript]]></category>

		<category><![CDATA[Performance]]></category>

		<category><![CDATA[innerhtml]]></category>

		<guid isPermaLink="false">http://blog.stevenlevithan.com/archives/faster-than-innerhtml</guid>
		<description><![CDATA[This post isn't about the pros and cons of innerHTML vs. W3C DOM methods. That has been hashed and rehashed elsewhere. Instead, I'll show how you can combine the use of innerHTML and DOM methods to make your code potentially hundreds of times faster than innerHTML on its own, when working with large numbers of [...]]]></description>
			<content:encoded><![CDATA[<p>This post isn't about the pros and cons of <code>innerHTML</code> vs. W3C DOM methods. That has been hashed and rehashed <a href="http://www.dustindiaz.com/innerhtml-vs-dom-methods/">elsewhere</a>. Instead, I'll show how you can combine the use of <code>innerHTML</code> and DOM methods to make your code potentially hundreds of times faster than <code>innerHTML</code> on its own, when working with large numbers of elements.</p>

<p>In some browsers (most notably, Firefox), although <code>innerHTML</code> is generally much faster than DOM methods, it spends a disproportionate amount of time clearing out existing elements vs. creating new ones. Knowing this, we can combine the speed of destroying elements by removing their parent using the standard DOM methods with creating new elements using <code>innerHTML</code>. (This technique is something I discovered during the development of <a href="http://regexpal.com" title="JavaScript regex tester">RegexPal</a>, and is one of its two main performance optimizations. The other is one-shot markup generation for match highlighting, which avoids needing to loop over matches or reference them individually.)</p>

<h3 class="sub">The code:</h3>

<pre class="code">
function replaceHtml(el, html) {
	var oldEl = typeof el === "string" ? document.getElementById(el) : el;
	/*@cc_on <span class="comment">// Pure innerHTML is slightly faster in IE</span>
		oldEl.innerHTML = html;
		return oldEl;
	@*/
	var newEl = oldEl.cloneNode(false);
	newEl.innerHTML = html;
	oldEl.parentNode.replaceChild(newEl, oldEl);
	<span class="comment">/* Since we just removed the old element from the DOM, return a reference
	to the new element, which can be used to restore variable references. */</span>
	return newEl;
};
</pre>

<p>You can use the above as <code>el = replaceHtml(el, newHtml)</code> instead of <code>el.innerHTML = newHtml</code>.</p>

<h3 class="sub">innerHTML is already pretty fast...is this really warranted?</h3>

<p>That depends on how many elements you're overwriting. In RegexPal, every keydown event potentially triggers the destruction and creation of thousands of elements (in order to make the syntax and match highlighting work). In such cases, the above approach has enormous positive impact. Even something as simple as <code>el.innerHTML += str</code> or <code>el.innerHTML = ""</code> could be a performance disaster if the element you're updating happens to have a few thousand children.</p>

<p>I've created a page which allows you to easily <a href="http://stevenlevithan.com/demo/replaceHtml.html" class="bold">test the performance difference</a> of <code>innerHTML</code> and my <code>replaceHtml</code> function with various numbers of elements. Make sure to try it out in a few browsers for comparison. Following are a couple examples of typical results from Firefox 2.0.0.6 on my system:</p>

<pre class="code"><span class="comment"><strong>1000 elements...</strong></span>
innerHTML (destroy only): <strong>156ms</strong>
innerHTML (create only): <strong>15ms</strong>
innerHTML (destroy &amp; create): <strong>172ms</strong>
replaceHtml (destroy only): <strong>0ms</strong> (<span class="comment"><strong>faster</strong></span>)
replaceHtml (create only): <strong>15ms</strong> (~ same speed)
replaceHtml (destroy &amp; create): <strong>15ms</strong> (<span class="comment"><strong>11.5x faster</strong></span>)

<span class="comment"><strong>15000 elements...</strong></span>
innerHTML (destroy only): <strong>14703ms</strong>
innerHTML (create only): <strong>250ms</strong>
innerHTML (destroy &amp; create): <strong>14922ms</strong>
replaceHtml (destroy only): <strong>31ms</strong> (<span class="comment"><strong>474.3x faster</strong></span>)
replaceHtml (create only): <strong>250ms</strong> (~ same speed)
replaceHtml (destroy &amp; create): <strong>297ms</strong> (<span class="comment"><strong>50.2x faster</strong></span>)
</pre>

<p>I think the numbers speak for themselves. Comparable performance improvements can also be seen in Safari. In Opera, <code>replaceHtml</code> is still typically faster than <code>innerHTML</code>, but by a narrower margin. In IE, simple use of <code>innerHTML</code> is typically faster than mixing it with DOM methods, but not by nearly the same kinds of margins as you can see above. Nevertheless, IE's conditional compilation feature is used to avoid the relatively minor performance penalty, by just using <code>innerHTML</code> with that browser.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.stevenlevithan.com/archives/faster-than-innerhtml/feed</wfw:commentRss>
		</item>
	</channel>
</rss>
