<?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"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>I does Javascript! &#187; Performance</title>
	<atom:link href="http://blog.stchur.com/category/performance/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.stchur.com</link>
	<description>If you don&#039;t expect too much from me, you might not be let down.</description>
	<lastBuildDate>Tue, 03 Jan 2012 16:01:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Palindromes</title>
		<link>http://blog.stchur.com/2008/06/14/palindromes/</link>
		<comments>http://blog.stchur.com/2008/06/14/palindromes/#comments</comments>
		<pubDate>Sat, 14 Jun 2008 19:06:11 +0000</pubDate>
		<dc:creator>sstchur</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Javascript basics]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Useful Functions]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[palindrome]]></category>

		<guid isPermaLink="false">http://blog.stchur.com/2008/06/14/palindromes/</guid>
		<description><![CDATA[The other evening while I was watching TV, I happened to have my laptop out, so I started dabbling around in Firebug just for the heck of it. I'll often just start writing functions for no particular reason, other than to refresh my skills or perhaps discover something about Javascript that I hadn't previously known. [...]]]></description>
			<content:encoded><![CDATA[	<p>The other evening while I was watching TV, I happened to have my laptop out, so I started dabbling around in Firebug just for the heck of it.  I'll often just start writing functions for no particular reason, other than to refresh my skills or perhaps discover something about Javascript that I hadn't previously known.</p>
	<p>So I was monkeying around, and I decided to write a function to determine if a string were a <a href = "http://en.wikipedia.org/wiki/Palindrome" title = "Wikipedia: Palindrome">palindrome</a>.  This is not a very difficult problem, but it might make for a descent introductory interview question (one of those questions you'd ask to rule out the truly inept).</p>
	<p>With problems like this, I'm mostly interested in two things:</p>
	<ol>
	<li>Writing the function in a clever way, so as to achieve the least amount of code possible</li>
	<li>Writing the function in the most efficient way possible</li>
	</ol>
	<p>Now, if it were Ruby, writing the clever solution (which might also happen to be the most efficient solution in that language -- not sure) would be ridiculously easy:</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw1">def</span> pal<span class="br0">&#40;</span>s<span class="br0">&#41;</span><br />
&nbsp; &nbsp;s == s.<span class="me1">reverse</span><br />
<span class="kw1">end</span></div>
	<p>That's so trivial, it's probably not even worth writing.</p>
	<p>But Javascript doesn't have a .reverse() method on strings, so you have to take an extra step (still pretty easy though):</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw2">function</span> pal<span class="br0">&#40;</span>s<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw1">return</span> s === s.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">''</span><span class="br0">&#41;</span>.<span class="me1">reverse</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">join</span><span class="br0">&#40;</span><span class="st0">''</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></div>
	<p>Split the string into an array, reverse the array, and then join it back together.  Since this is all native Javascript stuff, it turns out to be reasonably fast, though one might expect you could do better.</p>
	<p>For grins and giggles, I decided to see how a manual solution, where I compare characters starting at each end of the string and work towards the middle, would compare:</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw2">function</span> pal<span class="br0">&#40;</span>s<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw2">var</span> i, j,<br />
&nbsp; &nbsp;len = s.<span class="me1">length</span>,<br />
&nbsp; &nbsp;mid = Math.<span class="me1">floor</span><span class="br0">&#40;</span>len / <span class="nu0">2</span><span class="br0">&#41;</span>;</p>
	<p>&nbsp; &nbsp;<span class="kw1">for</span> <span class="br0">&#40;</span>i = <span class="nu0">0</span>, j = len - <span class="nu0">1</span>; i &lt; mid; i++, j--<span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span>s.<span class="me1">charAt</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span> !== s.<span class="me1">charAt</span><span class="br0">&#40;</span>j<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;<span class="kw1">return</span> <span class="kw2">true</span>;<br />
<span class="br0">&#125;</span></div>
	<p>This function will probably fail quickly, so that's good, but it also turns out to be generally faster than the split/reverse/join version.  It makes sense, since you're going through the string only one time and twice as fast as normal since you're traversing from both ends at the same time.</p>
	<p>Can you do even better though?  Maybe.  At least in Firefox you can, and quick tests seemed to confirm across other browsers too (but I didn't test extensively).</p>
	<p>What if we split the string in half, and only reverse half of it.  Then we can compare the first half with the original half:</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw2">function</span> pal<span class="br0">&#40;</span>s<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw2">var</span> len = s.<span class="me1">length</span>,<br />
&nbsp; &nbsp;x = len / <span class="nu0">2</span>,<br />
&nbsp; &nbsp;y = x === Math.<span class="me1">floor</span><span class="br0">&#40;</span>x<span class="br0">&#41;</span> ? x : <span class="br0">&#40;</span>x = Math.<span class="me1">floor</span><span class="br0">&#40;</span>x<span class="br0">&#41;</span><span class="br0">&#41;</span> + <span class="nu0">1</span>;</p>
	<p>&nbsp; &nbsp;<span class="kw1">return</span> s.<span class="me1">substr</span><span class="br0">&#40;</span><span class="nu0">0</span>, x<span class="br0">&#41;</span>.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">''</span><span class="br0">&#41;</span>.<span class="me1">reverse</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">join</span><span class="br0">&#40;</span><span class="st0">''</span><span class="br0">&#41;</span> === s.<span class="me1">substr</span><span class="br0">&#40;</span>y,len<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></div>
	<p>The idea here is just split the string in half, reverse one of the two pieces and compare them.  For example:</p>
	<p>TOOT: splits into "TO" and "OT."  Reverse one of them, say the second part ("OT") and compare.</p>
	<p>If you've got a odd number of characters, you can ignore the middle most character:</p>
	<p>RACECAR: splits into "RAC" and "CAR" (ignore the "E" in the middle).  Reverse the second part ("CAR") and compare.</p>
	<p>As it turned out, this seemed to be faster than the other two methods.  Not by orders of magnitude, but not insignificantly either.  Here are the number from Firefox, running each function 10,000 time on the string "gohangasalamiimalasagnahog" (go hang a salami, i'm a lasagna hog).</p>
	<ul>
	<li>(Traverse from both ends): 797ms</li>
	<li>(Split/Reverse/Join): 969ms</li>
	<li>(Compare halves): 640ms</li>
	</ul>
	<p>Of course, numbers varied slightly during each run, but overall the they were consistent relative to each other.</p>
	<p>So there ya go.  Nothing in particular I wanted to point out here; just found it interesting and thought you might too.</p>
	<p>Think my code sucks?  Got a better solution?  Say so in the comments (you won't hurt my feelings).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stchur.com/2008/06/14/palindromes/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Clean up after your event listeners</title>
		<link>http://blog.stchur.com/2007/09/06/clean-up-after-your-event-listeners/</link>
		<comments>http://blog.stchur.com/2007/09/06/clean-up-after-your-event-listeners/#comments</comments>
		<pubDate>Thu, 06 Sep 2007 06:01:02 +0000</pubDate>
		<dc:creator>sstchur</dc:creator>
				<category><![CDATA[Beating IE into submission]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Javascript basics]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://stchur.com/blog2/2007/09/06/clean-up-after-your-event-listeners/</guid>
		<description><![CDATA[Memory leaks in Javascript are, unfortunately, a very real problem. Of course, it seems to be a problem mostly in IE (try disabling all add-ons if you think you're seeing them in Firefox). While there are a number of ways that memory can be leaked, I find that one of the most significant (and most [...]]]></description>
			<content:encoded><![CDATA[	<p>Memory leaks in Javascript are, unfortunately, a very real problem. Of course, it seems to be a problem mostly in IE (try disabling all add-ons if you think you're seeing them in Firefox).  While there are a number of ways that memory can be leaked, I find that one of the most significant (and most frequent) causes is failing to remove event handlers.</p>
	<div class = "note">
	<p><em>Important Update:</em>  I failed to mention when I originally wrote this post, that you should use caution with this 'unload' technique.  If you are manually unhooking events throughout the life of your web-app (or taking care to manually unhook them on 'unload'), then you might potentially be adding multiple (and unnecessary) 'unload' handlers to the browser.</p>
	<p>This might not seem like a big deal, but in a large and complex app it can actually <em>increase</em> memory consumption dramatically, thereby negating any gain you'd have gotten from the technique!</p>
	</div>
	<h3>Auto Detach with 'unload'</h3>
	<p>In IE, if you wire up an event listener and fail to remove that listener when your page unloads, you're probably asking for a leak. One effective technique to ensure that listeners get removed is to wire up an 'unload' event to the window which detaches the listener for you.  For example:</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw2">var</span> elem = document.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">'someElem'</span><span class="br0">&#41;</span>;<br />
elem.<span class="me1">attachEvent</span><span class="br0">&#40;</span><span class="st0">'onclick'</span>, elemClick<span class="br0">&#41;</span>;<br />
window.<span class="me1">attachEvent</span><span class="br0">&#40;</span><span class="st0">'onunload'</span>, <span class="kw2">function</span><span class="br0">&#40;</span>e<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;elem.<span class="me1">detachEvent</span><span class="br0">&#40;</span><span class="st0">'onclick'</span>, elemClick<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><span class="br0">&#41;</span>;</div>
	<p>Keen readers might have noticed that I solved one problem (removing the 'click' listener from <code>elem</code>) by creating another one (attaching a new, anonymous listener to the windows's 'unload' event).</p>
	<h3>Why is this a problem?</h3>
	<p>In a <a href = "http://ecmascript.stchur.com/2007/01/02/anonymous-function-quick-tips/">previous blog entry</a>, I mentioned that it wasn't possible to remove an event listener if that listener were anonymous, as in:</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="co1">// IE specific code</span><br />
<span class="kw2">var</span> elem = document.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">'someElem'</span><span class="br0">&#41;</span>;<br />
elem.<span class="me1">attachEvent</span><span class="br0">&#40;</span><span class="st0">'onclick'</span>, <span class="kw2">function</span><span class="br0">&#40;</span>e<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw3">alert</span><span class="br0">&#40;</span><span class="st0">'you clicked it!'</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><span class="br0">&#41;</span>;</p>
	<p>elem.<span class="me1">detachEvent</span><span class="br0">&#40;</span><span class="st0">'onclick'</span>, <span class="kw2">function</span><span class="br0">&#40;</span>e<span class="br0">&#41;</span>&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// WON'T WORK!</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw3">alert</span><span class="br0">&#40;</span><span class="st0">'you clicked it!'</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><span class="br0">&#41;</span>;</div>
	<p>While it's true that the above code won't work, it's not <em>entirely</em> true to say that it's impossible to remove an anonymous listener. Why?  Because every function actually has a reference to itself through its own <code>arguments</code> object.  Specifically, through the <code>.callee</code> property of the <code>arguments</code> object.</p>
	<p>We can use this to our advantage to detach the anonymous 'unload' listener from <em>within</em> the listener itself.</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw2">var</span> elem = document.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">'someElem'</span><span class="br0">&#41;</span>;<br />
elem.<span class="me1">attachEvent</span><span class="br0">&#40;</span><span class="st0">'onclick'</span>, elemClick<span class="br0">&#41;</span>;<br />
window.<span class="me1">attachEvent</span><span class="br0">&#40;</span><span class="st0">'onunload'</span>, <span class="kw2">function</span><span class="br0">&#40;</span>e<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;elem.<span class="me1">detachEvent</span><span class="br0">&#40;</span><span class="st0">'onclick'</span>, elemClick<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;window.<span class="me1">detachEvent</span><span class="br0">&#40;</span><span class="st0">'onunload'</span>, arguments.<span class="me1">callee</span><span class="br0">&#41;</span>;&nbsp; &nbsp; &nbsp;<span class="co1">// detach this anonymous listener</span><br />
<span class="br0">&#125;</span><span class="br0">&#41;</span>;</div>
	<h3>Why not just un-anonymize?</h3>
	<p>You certainly could just name all of your functions and then refer to them by name, but sometimes anonymous functions are very useful since they allow to create closures and do other nifty Javascript tricks.  In those cases where it's desirable to use an anonymous function, this technique might be just the ticket!</p>
	<h3>Conclusion</h3>
	<p>I've conveniently (for me anyway) left out any non IE-specific code in this post.  It's worth nothing that I don't generally use this technique except in IE, which means a little cross browser code is in order to ensure that this 'onunload' technique is only used for that browser.</p>
	<p>Of course, it isn't going to hurt anything for other browsers (and it might even help) so there'd be no harm is using it across the board, bu you'll still need to write some cross-browser code (obviously).  I'll leave that as an exercise for the reader though.</p>
	<p>Happy scripting.</p>
	<p>Comments welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stchur.com/2007/09/06/clean-up-after-your-event-listeners/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Avoiding recursion in Javascript</title>
		<link>http://blog.stchur.com/2007/07/06/avoiding-recursion-in-javascript/</link>
		<comments>http://blog.stchur.com/2007/07/06/avoiding-recursion-in-javascript/#comments</comments>
		<pubDate>Fri, 06 Jul 2007 19:41:57 +0000</pubDate>
		<dc:creator>sstchur</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://stchur.com/blog2/2007/07/06/avoiding-recursion-in-javascript/</guid>
		<description><![CDATA[Recursion can often lead to elegant and short solutions (one of the reasons I like it so much), but it can, most definitely, be misused. Learning recursion in school I think just about every computer science course I've ever taken that (even remotely) mentions recursion, uses either factorial or Fibonacci as the starter sample to [...]]]></description>
			<content:encoded><![CDATA[	<p><a href = "http://en.wikipedia.org/wiki/Recursion">Recursion</a> can often lead to elegant and short solutions (one of the reasons I like it so much), but it can, most definitely, be misused.</p>
	<h3>Learning recursion in school</h3>
	<p>I think just about every computer science course I've ever taken that (even remotely) mentions recursion, uses either factorial or Fibonacci as the starter sample to help students gets their heads around the concept.  This is okay (I guess) as long as it's made clear that recursion is not the optimal solution for either of these.</p>
	<p>It was in fact made clear to me in school that recursion is not ideal for factorial and Fibonacci, but for some reason that didn't stop me from using a recursive factorial function once.</p>
	<div class="dean_ch" style="white-space: nowrap;">
<span class="kw2">function</span> fact<span class="br0">&#40;</span>n<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="kw1">return</span> n &lt;= <span class="nu0">1</span> ? <span class="nu0">1</span> : n * fact<span class="br0">&#40;</span>n<span class="nu0">-1</span><span class="br0">&#41;</span>; <span class="br0">&#125;</span><br />
&nbsp;</div>
	<p>This, it turned out, was not just a bad decision; it was a <em>horrible</em> decision.</p>
	<h3>Idiot me</h3>
	<p>I'm not proud of it, and I'm still not entirely sure what possessed me to do it (especially knowing full-well that the iterative solution is better).  Maybe it was my love of short, simple, readable code, or maybe my brain was just malfunctioning that day (but I tend towards the former; it's gotten me into trouble before).</p>
	<p>In fact, if I remember correctly, the exact thought that went through my head that day went something like this:</p>
	<blockquote><p>You know... I remember learning that a factorial function should never be written recursively (except perhaps as a teaching example) because the iterative solution is much more efficient.  But if I use recursion just this one time, I can get this nifty, one-line factorial function, and it looks just oh so pretty!  Plus, I won't be using this function very often at all, so I don't think it will matter much.</p></blockquote>
	<p>Boy did that (horrible) rationalization miss the mark!  It did matter, it mattered <em>a lot</em>.  And to make the situation worse, I <em>did</em> end up using the function often (very very very often, and that might be an understatement).</p>
	<h3>Why so many factorials?</h3>
	<p>Our profiling tool indicated that the factorial function was being invoked over a million times!  Whoa, now <em>that's</em> not good.  Did I mention this was all in Javascript?  Yeah, it was, so it's even worse.</p>
	<p>So why all the factorials?  Well, I was doing some fairly complex math involving <a href = "http://en.wikipedia.org/wiki/B%C3%A9zier_curve">Bezier curves</a>.  Part of that math involves <a href = "http://en.wikipedia.org/wiki/Choose">Binomial coefficients</a> which is defined as:</p>
	<div><code>n! / (k! * (n-k)!)</code></div>
	<p>The net effect of this was (roughly) a 7 second delay in the <abbr title = "Page Load Time">PLT</abbr> of the particular page in which this script was running.  Again, not good.</p>
	<h3>Lesson learned</h3>
	<p>So, as quickly as I could, I removed that dreadful (but pretty) one-line, recursive factorial function (hoping no one would notice) and replaced it with an iterative one.  This boosted performance tremendously -- only took about 400ms to perform the same calculation.</p>
	<p>Feeling so guilty for having made the poor decision to use recursion in the first place though, I still wasn't happy with my 400ms solution.  I decided to see what else I could do to improve the performance.  Turns out I was able to do some pre-computation and get the entire time down to about 48ms!</p>
	<p>Ah, now I feel redeemed.</p>
	<h3>Heed this warning</h3>
	<p>So let this be a lesson to you:  Use recursion wisely, only when appropriate, and in the case of Javascript, almost never!</p>
	<p>Comments welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stchur.com/2007/07/06/avoiding-recursion-in-javascript/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>IE innerHTML Memory Leak</title>
		<link>http://blog.stchur.com/2007/05/16/ie-innerhtml-memory-leak/</link>
		<comments>http://blog.stchur.com/2007/05/16/ie-innerhtml-memory-leak/#comments</comments>
		<pubDate>Wed, 16 May 2007 16:04:11 +0000</pubDate>
		<dc:creator>sstchur</dc:creator>
				<category><![CDATA[Beating IE into submission]]></category>
		<category><![CDATA[Javascript basics]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://stchur.com/blog2/2007/05/16/ie-innerhtml-memory-leak/</guid>
		<description><![CDATA[Kristoffer Henriksson has got to be one of the most intelligent people I know. His ability to write, test, and debug code is second the none. Heck, I wouldn't be surprised if the guy can read and write machine code as if it were English. Recently, Kristoffer did a significant amount of investigation to track [...]]]></description>
			<content:encoded><![CDATA[	<p><a href = "http://blogs.msdn.com/Kristoffer">Kristoffer Henriksson</a> has got to be one of <em>the</em> most intelligent people I know.  His ability to write, test, and debug code is second the none.  Heck, I wouldn't be surprised if the guy can read and write machine code as if it were English.</p>
	<p>Recently, Kristoffer did a significant amount of investigation to track down a nasty IE memory leak issue.  IE's problems with memory leaks are well known, but most of the time, you'll hear people saying things like "closures are the cause of memory leaks," or "failing to detach events is what causes memory leaks," and (probably the most common), "circular references are the culprit -- they cause memory leaks."</p>
	<p>To some degree, all of these things are true.  Closures can sometimes lead to memory leaks, failing to detach events can also lead to memory leaks, and yes, circular references to DOM elements can also be the cause of memory leaks.</p>
	<p>One kind of leak that seems to get a little less attention though, is the one involving <code>.innerHTML</code>.  Fortunately (thanks to Kristoffer's investigation) this one is pretty easy to deal with.</p>
	<p>Before we can deal with the leak, we need to understand what causes it.  Three conditions are required:</p>
	<ol>
	<li>A orphaned DOM element must exist in memory.</li>
	<li>That element's innerHTML must be set to a string of markup the creates an element with some DOM 0 event wired up.</li>
	<li>The aforementioned innerHTML property must be set <em>before</em> the orphaned DOM element is "unorphaned" (added to the page).</li>
	</ol>
	<p>If these conditions are met, get ready to call the (Javascript) plumber, because you've got a leak!</p>
	<p>To make things a little less abstract, I'll write some code and explain piece by piece, how it fits the conditions above:</p>
	<div class="dean_ch" style="white-space: nowrap;">
<span class="co1">// 1. &nbsp;An orphaned DOM element must exist in memory.</span><br />
<span class="kw2">var</span> elem = document.<span class="me1">createElement</span><span class="br0">&#40;</span><span class="st0">'div'</span><span class="br0">&#41;</span>;<br />
<span class="co1">// poor elem is just floating around in the page's memory without a parentNode</span></p>
	<p><span class="co1">// 2. &nbsp;elem's innerHTML must be set to a string of markup that creates an element with some DOM 0 event wired up.</span><br />
elem.<span class="me1">innerHTML</span> = <span class="st0">'&lt;a onclick = &quot;testFn()&quot;&gt;Test Link&lt;/a&gt;'</span>;<br />
<span class="co1">// elem contains an &lt;a&gt; tag with an onclick event</span></p>
	<p><span class="co1">// 3. &nbsp;elem is now added to the page, &lt;em&gt;after&lt;/em&gt; innerHTML has already been set.</span><br />
document.<span class="me1">body</span>.<span class="me1">appendChild</span><span class="br0">&#40;</span>elem<span class="br0">&#41;</span><br />
<span class="co1">// elem (and its child &lt;a&gt; tag) is now part of the page (remember, that innerHTML has already been set)</span></div>
	<p>As you can see, the code above is not at all an uncommon scenario.  Chances are though, if that's all you've got, you won't notice much of leak.  This issue really only manifests itself when multiplied, that is, when you set <code>.innerHTML</code> in the above manner over and over and over again on the same page.</p>
	<p>Why would ever do this?  Think Web 2.0, think AJAX, think dynamic page updates and you probably won't have to search too hard to find a situation where someone might do this.  Maybe you already know of (or helped write) a Web 2.0 app that does this.</p>
	<h3>Memory Leak Demo Page</h3>
	<p>Anyway, when above pattern <em>is</em> multiplied (whatever the reason) memory leaking chaos will ensue.  To illustrate the problem, I've put together a sample page  with a script that creates a orphaned &lt;div&gt; element, whose <code>.innerHTML</code> is set to a string of 2000 &lt;a&gt; tags with onclick events.  When you click the "Start Leak" button, the script executes repeatedly, until you click the "Stop Leak" button.  This give you a chance to use Perfmon to monitor memory consumption and see the results of the leak. The memory leak demo page can be found <a href = "http://ecmascript.stchur.com/blogcode/ie_innerhtml_memleak/leak.html">here</a>.</p>
	<h3>The solution</h3>
	<p>It turns out, the solution is actually pretty easy:  simply make sure to set <code>.innerHTML</code> <em>after</em> appending the DOM element to the page.  That's it!</p>
	<div class="dean_ch" style="white-space: nowrap;">
<span class="co1">// create the element in memory</span><br />
<span class="kw2">var</span> elem = document.<span class="me1">createElement</span><span class="br0">&#40;</span><span class="st0">'div'</span><span class="br0">&#41;</span>;</p>
	<p><span class="co1">// add it to the page before setting .innerHTML</span><br />
document.<span class="me1">body</span>.<span class="me1">appendChild</span><span class="br0">&#40;</span>elem<span class="br0">&#41;</span></p>
	<p><span class="co1">// now it's safe to set .innerHTML</span><br />
elem.<span class="me1">innerHTML</span> = <span class="st0">'&lt;a onclick = &quot;testFn()&quot;&gt;Test Link&lt;/a&gt;'</span>;</div>
	<div class = "note">
Of course there are other solutions, one of which is to avoid using <code>.innerHTML</code> at all.  As a general best practice, I encourage this (for a number of reasons that I don't have time to get into here), but I recognize that that suggestion may not also be desirable, or practical.
</div>
	<p>To see that this really does take care of the issue, I've put together another <a href = "http://ecmascript.stchur.com/blogcode/ie_innerhtml_memleak/noleak.html">test page</a>.  In this one, the <code>.innerHTML</code> property is only set <em>after</em> the DOM element has been added to the page.</p>
	<p>If you click the "Start Leak" button on each page and let it run for about 60 seconds or so, you should notice that the first page continues to consume more and more memory as time goes on, whereas the second page's memory consumptions remains relatively constant.</p>
	<h3>Demo Links</h3>
	<p>In case you're the kind of person who doesn't like to read paragraphs to find embedded links (I'm like that), here are the links to the two demo pages, for your convenicne:</p>
	<ul>
	<li><a href = "http://ecmascript.stchur.com/blogcode/ie_innerhtml_memleak/leak.html">Leak Demo</a></li>
	<li><a href = "http://ecmascript.stchur.com/blogcode/ie_innerhtml_memleak/noleak.html">No Leak Demo</a></li>
	</ul>
	<p>So there ya go: a nasty bug, but thanks to Kristoffer's work tracking tracking down the exact causes of this leak, a fairly easy one to handle.</p>
	<p>Comments welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stchur.com/2007/05/16/ie-innerhtml-memory-leak/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>

