<?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>Calyptus Life &#187; Performance</title>
	<atom:link href="http://blog.calyptus.eu/tags/performance/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.calyptus.eu</link>
	<description>Advanced web application development tactics - from scalability to UI design</description>
	<lastBuildDate>Wed, 28 Dec 2011 10:31:02 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>JavaScript Call Performance &#8211; Just Inline It</title>
		<link>http://blog.calyptus.eu/seb/2011/01/javascript-call-performance-just-inline-it/</link>
		<comments>http://blog.calyptus.eu/seb/2011/01/javascript-call-performance-just-inline-it/#comments</comments>
		<pubDate>Mon, 24 Jan 2011 23:46:49 +0000</pubDate>
		<dc:creator>Sebastian Markbåge</dc:creator>
				<category><![CDATA[Client Side]]></category>
		<category><![CDATA[Classes]]></category>
		<category><![CDATA[Compiler]]></category>
		<category><![CDATA[Inlining]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Optimization]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://blog.calyptus.eu/?p=371</guid>
		<description><![CDATA[There are a couple of well-known micro optimization techniques when you need that extra speed within an expensive loop. It generally comes down to eliminating function calls and flattening the closure scope.
Intuitively you don&#8217;t want to bloat your download size with repeated code. You also want a clear separation of concerns to make your code [...]]]></description>
			<content:encoded><![CDATA[<p>There are a couple of well-known micro optimization techniques when you need that extra speed within an expensive loop. It generally comes down to eliminating function calls and flattening the closure scope.</p>
<p>Intuitively you don&#8217;t want to bloat your download size with repeated code. You also want a clear separation of concerns to make your code understandable and managable. You want to separate common code into sub-routines (functions).</p>
<p><strong>Intra-object method calls</strong></p>
<p>I&#8217;ve done <a href="http://jsperf.com/classes-with-inner-function-calls-instantiation">a number</a> <a href="http://jsperf.com/classes-with-inner-function-calls">of tests</a> <a href="http://jsperf.com/classes-with-many-inner-function-calls">on repeated calls</a> within a single object. This is typically where an expensive loop would occur.</p>
<p>Now you might think that property look-ups are expensive and should be avoided. Since in a naive implementation they would be continued hash-table look-ups. However, traversing closure scopes and .call(bind) invocations tend to be more expensive in real world engines. Generally, you are better off invoking the function, by property name, on the same prototype &#8211; continuously. Engines optimize for this pattern. In the tests you can see that this is even more prevalent in recent optimizations.</p>
<p><strong>Super/base method calls</strong></p>
<p>In Class-oriented/OOP patterns, you often see the need to override an inherited method. However, while doing so you wish to call the overridden (super/base/parent) function from within the new one.</p>
<p>The most common way of doing this is by storing a reference to the prototype object, then invoking the function using .call() or .apply() to set the &#8220;this&#8221; context to the right value. However, as I&#8217;ve shown, navigating a closure and invoking the function using .call() is more expensive than invoking prototype methods.</p>
<p>The benefit of storing a reference to the prototype is that you get a live property that can be monkey patched with a new super function on the fly. However, relying on this pattern can be tricky.</p>
<p>You&#8217;re better off having a module system that supports proper file ordering of monkey patches. Where monkey patches are applied before any child modules inherit from their parent. This will enable better optimization on engines that depend on declaration order to optimize their hidden classes (like V8). It also enables monkey patching of mixins that are copied. I.e. has no live inheritance (since JS doesn&#8217;t support multiple inheritance).</p>
<p>If we can assume that we don&#8217;t need on-the-fly updates of super functions, then we can optimize this further. Again, <a href="http://jsperf.com/super-call">my tests</a> show, that it&#8217;s faster to invoke a method on the same prototype than finding a function reference and invoking .call().</p>
<p>I&#8217;ve toyed with some <a href="https://gist.github.com/790455">syntax experiments</a> to make this prettier.</p>
<p><strong>Just Inline It</strong></p>
<p><a href="http://twitter.com/steida">Daniel Steigerwald</a> pointed out that once you make the assumption that we don&#8217;t need on-the-fly monkey patches, you should just inline the code. This is always faster.</p>
<p>Let&#8217;s take a look at some nonsensical code. The function bar calls the function foo four times.</p>

<div class="wp_codebox"><table width="100%" ><tr id="p3713"><td class="code" id="p371code3"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> foo<span style="color: #009900;">&#40;</span>state<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> my <span style="color: #339933;">=</span> <span style="color: #3366CC;">'code'</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> l <span style="color: #339933;">=</span> my.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> l<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">%</span> <span style="color: #CC0000;">10</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span>
            state.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>my<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">==</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span>
            state.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>my<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>l <span style="color: #339933;">==</span> <span style="color: #CC0000;">2</span> <span style="color: #339933;">&amp;&amp;</span> i <span style="color: #339933;">==</span> <span style="color: #CC0000;">3</span><span style="color: #009900;">&#41;</span>
            state.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'foo'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">else</span>
            state.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'else'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">return</span> my<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> bar<span style="color: #009900;">&#40;</span>condition<span style="color: #339933;">,</span> state<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">var</span> complexCondition <span style="color: #339933;">=</span> <span style="color: #339933;">!</span>condition <span style="color: #339933;">&amp;&amp;</span> state.<span style="color: #660066;">length</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">3</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">var</span> value <span style="color: #339933;">=</span> state<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>condition<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        value <span style="color: #339933;">=</span> foo<span style="color: #009900;">&#40;</span>state<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>complexCondition<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
            state.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'someData'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            value <span style="color: #339933;">=</span> foo<span style="color: #009900;">&#40;</span>state<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>value.<span style="color: #660066;">length</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">5</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
            value <span style="color: #339933;">=</span> foo<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>value <span style="color: #339933;">==</span> <span style="color: #3366CC;">'else'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        	value <span style="color: #339933;">=</span> foo<span style="color: #009900;">&#40;</span>state<span style="color: #009900;">&#41;</span>
        	state.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'test'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        condition <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>value <span style="color: #339933;">==</span> <span style="color: #3366CC;">'foo'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>This file weighs in at about 300 bytes gzipped.</p>
<p>If we instead inline (copy) the foo code into all four places in the bar function. We get something like this.</p>

<div class="wp_codebox"><table width="100%" ><tr id="p3714"><td class="code" id="p371code4"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> bar<span style="color: #009900;">&#40;</span>condition<span style="color: #339933;">,</span> state<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">var</span> complexCondition <span style="color: #339933;">=</span> <span style="color: #339933;">!</span>condition <span style="color: #339933;">&amp;&amp;</span> state.<span style="color: #660066;">length</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">3</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">var</span> value <span style="color: #339933;">=</span> state<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>condition<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
            <span style="color: #003366; font-weight: bold;">var</span> stack <span style="color: #339933;">=</span> state<span style="color: #339933;">;</span>
			<span style="color: #003366; font-weight: bold;">var</span> my <span style="color: #339933;">=</span> <span style="color: #3366CC;">'code'</span><span style="color: #339933;">;</span>
			<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> l <span style="color: #339933;">=</span> my.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> l<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
				<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">%</span> <span style="color: #CC0000;">10</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span>
					stack.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>my<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">==</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span>
					stack.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>my<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>l <span style="color: #339933;">==</span> <span style="color: #CC0000;">2</span> <span style="color: #339933;">&amp;&amp;</span> i <span style="color: #339933;">==</span> <span style="color: #CC0000;">3</span><span style="color: #009900;">&#41;</span>
					stack.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'foo'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #000066; font-weight: bold;">else</span>
					stack.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'else'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			value <span style="color: #339933;">=</span> my<span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>complexCondition<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
            state.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'someData'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #003366; font-weight: bold;">var</span> stack <span style="color: #339933;">=</span> state<span style="color: #339933;">;</span>
			<span style="color: #003366; font-weight: bold;">var</span> my <span style="color: #339933;">=</span> <span style="color: #3366CC;">'code'</span><span style="color: #339933;">;</span>
			<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> l <span style="color: #339933;">=</span> my.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> l<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
				<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">%</span> <span style="color: #CC0000;">10</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span>
					stack.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>my<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">==</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span>
					stack.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>my<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>l <span style="color: #339933;">==</span> <span style="color: #CC0000;">2</span> <span style="color: #339933;">&amp;&amp;</span> i <span style="color: #339933;">==</span> <span style="color: #CC0000;">3</span><span style="color: #009900;">&#41;</span>
					stack.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'foo'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #000066; font-weight: bold;">else</span>
					stack.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'else'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			value <span style="color: #339933;">=</span> my<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>value.<span style="color: #660066;">length</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">5</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
            <span style="color: #003366; font-weight: bold;">var</span> stack <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
			<span style="color: #003366; font-weight: bold;">var</span> my <span style="color: #339933;">=</span> <span style="color: #3366CC;">'code'</span><span style="color: #339933;">;</span>
			<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> l <span style="color: #339933;">=</span> my.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> l<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
				<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">%</span> <span style="color: #CC0000;">10</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span>
					stack.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>my<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">==</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span>
					stack.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>my<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>l <span style="color: #339933;">==</span> <span style="color: #CC0000;">2</span> <span style="color: #339933;">&amp;&amp;</span> i <span style="color: #339933;">==</span> <span style="color: #CC0000;">3</span><span style="color: #009900;">&#41;</span>
					stack.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'foo'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #000066; font-weight: bold;">else</span>
					stack.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'else'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			value <span style="color: #339933;">=</span> my<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>value <span style="color: #339933;">==</span> <span style="color: #3366CC;">'else'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
            <span style="color: #003366; font-weight: bold;">var</span> stack <span style="color: #339933;">=</span> state<span style="color: #339933;">;</span>
			<span style="color: #003366; font-weight: bold;">var</span> my <span style="color: #339933;">=</span> <span style="color: #3366CC;">'code'</span><span style="color: #339933;">;</span>
			<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> l <span style="color: #339933;">=</span> my.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> l<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
				<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">%</span> <span style="color: #CC0000;">10</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span>
					stack.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>my<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">==</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span>
					stack.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>my<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>l <span style="color: #339933;">==</span> <span style="color: #CC0000;">2</span> <span style="color: #339933;">&amp;&amp;</span> i <span style="color: #339933;">==</span> <span style="color: #CC0000;">3</span><span style="color: #009900;">&#41;</span>
					stack.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'foo'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #000066; font-weight: bold;">else</span>
					stack.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'else'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			value <span style="color: #339933;">=</span> my<span style="color: #339933;">;</span>
        	state.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'test'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        condition <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>value <span style="color: #339933;">==</span> <span style="color: #3366CC;">'foo'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>This file weighs about 290 bytes gzipped. Wait, what? We more than doubled the original file size but the result is smaller?</p>
<p>Yes, the GZIP compression uses the <a href="http://en.wikipedia.org/wiki/LZ77">LZ77</a> algorithm to find repeated byte sequences. This means that inlining your code may actually result in smaller download sizes since some plumbing code is removed.</p>
<p>Is it cheating to compare gzipped file size instead of originals? No. You should always send your static uncompressed content using the GZIP compression. It&#8217;s cheap. This is the real world baseline. You should optimize for this.</p>
<p>There are some quirks to look out for. Some minifiers rename variables inconsistently. This may result in inconsistent sequences. You should look out for this, since that would cause a larger file size.</p>
<p>The larger code base may cause a slightly slower start up, since the JS engine needs to parse and compile more code. This should be very very minimal though. Remember, we&#8217;re optimizing for tight loops here.</p>
<p><strong>JS-to-JS Compilers</strong></p>
<p>Our inlined code is ugly and unmaintainable. Luckily there are tools that can inline pretty source code for us. E.g. the <a href="http://closure-compiler.appspot.com">Google Closure Compiler</a>. Unfortunately the Closure Compiler doesn&#8217;t seem to inline functions that are called more than once. Neither does it use these optimization techniques for super calls. Perhaps there are settings that I&#8217;m not aware of.</p>
<p>Recursive functions may be difficult to inline but there are tools that can rewrite these and do tail call optimizations as well.</p>
<p>However, this is just a hint of the awesomeness that could be achieved by using a custom JS-to-JS compiler. More on that later.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.calyptus.eu/seb/2011/01/javascript-call-performance-just-inline-it/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>The Performance of .nodeName</title>
		<link>http://blog.calyptus.eu/seb/2009/11/the-performance-of-nodename/</link>
		<comments>http://blog.calyptus.eu/seb/2009/11/the-performance-of-nodename/#comments</comments>
		<pubDate>Tue, 24 Nov 2009 05:43:01 +0000</pubDate>
		<dc:creator>Sebastian Markbåge</dc:creator>
				<category><![CDATA[Client Side]]></category>
		<category><![CDATA[DOM]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://blog.calyptus.eu/?p=177</guid>
		<description><![CDATA[I was researching various options of traversing nodes for Slick and the DOM Range for MooTools. I realized that the nodeName property is incredibly slow to access in WebKit browsers. This is because it is working with qualified names (with namespaces and stuff) internally.

if &#40;node.nodeName == 'A'&#41; // do something with anchor tag

If you add [...]]]></description>
			<content:encoded><![CDATA[<p>I was researching various options of traversing nodes for <a href="http://github.com/subtleGradient/slick">Slick</a> and the <a href="http://github.com/calyptus/mootools-more/tree/range/Source/Native/">DOM Range for MooTools</a>. I realized that the nodeName property is incredibly slow to access in WebKit browsers. This is because it is working with qualified names (with namespaces and stuff) internally.</p>

<div class="wp_codebox"><table width="100%" ><tr id="p1777"><td class="code" id="p177code7"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>node.<span style="color: #660066;">nodeName</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">'A'</span><span style="color: #009900;">&#41;</span> <span style="color: #006600; font-style: italic;">// do something with anchor tag</span></pre></td></tr></table></div>

<p>If you add case insensitive matching to that it will be even slower.</p>
<p>Instead I decided to try to check the constructor of the node to determine what type it is. For example for the anchor (A) tag, modern browsers will use the prototype of HTMLAnchorElement. This can potentially speed up these checks if you&#8217;re looking for a known node type.</p>

<div class="wp_codebox"><table width="100%" ><tr id="p1778"><td class="code" id="p177code8"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>node.<span style="color: #660066;">constructor</span> <span style="color: #339933;">===</span> HTMLAnchorElement<span style="color: #009900;">&#41;</span> <span style="color: #006600; font-style: italic;">// do something</span>
<span style="color: #006600; font-style: italic;">// OR...</span>
<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>node <span style="color: #000066; font-weight: bold;">instanceof</span> HTMLAnchorElement<span style="color: #009900;">&#41;</span> <span style="color: #006600; font-style: italic;">// do something</span></pre></td></tr></table></div>

<p>I ran <a href="http://labs.calyptus.eu/NodeName/performance-test.html">this performance test</a> in various browsers. It traverses all nodes in a large HTML documents and checks which ones are anchor nodes. It first does a blank run to eliminate any initialization quirks. Then it does a control run without the anchor check. Then it tests each of the above models.</p>
<p><strong>IE6 and IE7</strong> will obviously fail since they don&#8217;t support the HTMLAnchorElement constructor/prototype. For that case you would have to fall back to the nodeName property.</p>
<p><strong>IE8</strong> will be slightly slower with the constructor check than the nodeName check. But the difference is marginal in the overall scope of IE&#8217;s slowness.</p>
<p><strong>WebKit</strong> will gain significant performance using the constructor check. The difference is relatively small to the overhead of manually walking the tree. However, if you take the control value from the blank run into account, the difference of just the node type checks will be significant (several times faster). The slow part is the WebKit DOM API, so you will see this with both JavaScriptCore and V8 (Safari and Chrome respectively).</p>
<p><strong>Firefox</strong> will be slower on the first run for some weird reason. But in subsequent runs the constructor check will be faster than the nodeName check.</p>
<p><em>As a side note, node.tagName is no different. That is just an alias for node.nodeName.</em></p>
<p><em>In <a href="http://ejohn.org/blog/nodename-case-sensitivity/">John Resig&#8217;s case sensitivity</a> he discusses the case inconsistencies of the nodeName property in various contexts and the impact on performance. For example, in IE, the value of nodeName of unknown elements (like the new HTML5 elements) keeps it original case as in the markup.</em></p>
<p><em>This means that any proper CSS selector search for such elements would have to run a case-insensitive match against the nodeName property. Unfortunately the little trick I&#8217;ve shown above doesn&#8217;t remedy this problem because unknown elements will be lacking a known constructor. However, known Elements can still utilize this trick as a slight performance boost, while letting unknown element fallback to a case insensitive match.</em></p>
<p><em>UPDATE: I added a case-insensitive match to the <a href="http://labs.calyptus.eu/NodeName/performance-test.html">performance tests</a> using regular expressions &#8211; showing the added overhead compared to constructor checking.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.calyptus.eu/seb/2009/11/the-performance-of-nodename/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

