<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>jpauclair</title>
	<atom:link href="http://jpauclair.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://jpauclair.net</link>
	<description>Ninjaneering!</description>
	<lastBuildDate>Thu, 24 May 2012 01:42:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='jpauclair.net' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>jpauclair</title>
		<link>http://jpauclair.net</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://jpauclair.net/osd.xml" title="jpauclair" />
	<atom:link rel='hub' href='http://jpauclair.net/?pushpress=hub'/>
		<item>
		<title>fastSort, faster is better!</title>
		<link>http://jpauclair.net/2012/03/12/fastsort-faster-is-better/</link>
		<comments>http://jpauclair.net/2012/03/12/fastsort-faster-is-better/#comments</comments>
		<pubDate>Tue, 13 Mar 2012 02:00:49 +0000</pubDate>
		<dc:creator>jpauclair</dc:creator>
				<category><![CDATA[actionscript]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[general]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[sort]]></category>

		<guid isPermaLink="false">http://jpauclair.net/?p=825</guid>
		<description><![CDATA[Today, Jackson Dunstan posted about how to use a profiler to get better performance in flash. For this post he decided to show how to use TheMiner&#8230; awesome! In this post he&#8217;s profiling two sorting method: native vector. sort, and Skyboy&#8217;s fastSort code. At first I was impressed by the result of Skyboy. Then I [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=825&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Today,<strong> Jackson Dunstan</strong> <a href="http://jacksondunstan.com/articles/1763" title="Jackson Dunstan - Profiler">posted about how to use a profiler</a> to get better performance in flash.<br />
For this post he decided to show how to use <a href="http://www.sociodox.com/theminer" title="TheMiner Flash Profiler">TheMiner</a>&#8230; awesome!</p>
<p>In this post he&#8217;s profiling two sorting method: native vector. sort, and Skyboy&#8217;s fastSort code.</p>
<p>At first I was impressed by the result of Skyboy. Then I realized two things.<br />
First, The flash native sort REALY don&#8217;t like Number.infinity, negative infinity.<br />
So when sorting and vector. with these values inside, it&#8217;s getting a LOT slower.<br />
Where a standard vector could take 100ms to sort, one with infinity values in it can take up to 2000ms!!</p>
<p>The other thing is fastSort is using void (*) pointer everywhere.<br />
So if we go back a few day to my <a href="http://jpauclair.net/2012/02/25/epic-memory-track-down/" title="Epic memory trackdown">previous (epic) article</a> , we know that this is a really bad thing when casting from void to Number.<br />
It&#8217;s allocating a LOT of memory. (<strong>5Mo/Sort on 50K elements</strong>)</p>
<p>So I decided to add a few hundreds lines to this class with already a lot of it (fastSort)<br />
I added a specific sorting method for int, uint and Number to manage only typed values.</p>
<p>The reslut is quite amazing!</p>
<p>Native Vector Sort : 100 ms + 400Ko allocation<br />
UnOptimized fastSort : 400 ms + 5Mo allocation<br />
<strong>New Optimized fastSort : 20ms + zero allocation</strong></p>
<p>Finaly, just before giving you the code, I want to invite you on a new little forum that focus on Performances, optimization, debugging and multiple other flash hardcore subjects.<br />
Many of the most hardcore dev and blogger I know are already in or are going to join soon, so please be part of this and enjoy posting refreshing and brain teasing content!<br />
The <a href="http://www.sociodox.com/forum/" title="Hardcore Flash Forum">Hardcore flash forum</a></p>
<p>And now.. the way too many lines of code part:<br />
<span id="more-825"></span></p>
<p><pre class="brush: as3;">
package skyboy.utils {
	
	/**
	 * Skyboy sort updated by Sociodox ( http://www.sociodox.com )
	 * fastSort, using typed native Number, int and uint
	 * Huge performance gain for all 3 type (2000%)
	 * Using Array.sort : 2000ms
	 * Using original fastSort : 400ms
	 * Using this typed fastSort : 20ms
	 * 2012/03/12
	 */
	
	/**
	 * fastSort by skyboy. February 26th 2011.
	 * Visit http://github.com/skyboy for documentation, updates
	 * and more free code.
	 *
	 *
	 * Copyright (c) 2010, skyboy
	 *    All rights reserved.
	 *
	 * Permission is hereby granted, free of charge, to any person
	 * obtaining a copy of this software and associated documentation
	 * files (the &quot;Software&quot;), to deal in the Software with
	 * restriction, with limitation the rights to use, copy, modify,
	 * merge, publish, distribute, sublicense copies of the Software,
	 * and to permit persons to whom the Software is furnished to do so,
	 * subject to the following conditions and limitations:
	 *
	 * ^ Attribution will be given to:
	 *  	skyboy, http://www.kongregate.com/accounts/skyboy;
	 *  	http://github.com/skyboy; http://skybov.deviantart.com
	 *
	 * ^ Redistributions of source code must retain the above copyright notice,
	 * this list of conditions and the following disclaimer in all copies or
	 * substantial portions of the Software.
	 *
	 * ^ Redistributions of modified source code must be marked as such, with
	 * the modifications marked and ducumented and the modifer's name clearly
	 * listed as having modified the source code.
	 *
	 * ^ Redistributions of source code may not add to, subtract from, or in
	 * any other way modify the above copyright notice, this list of conditions,
	 * or the following disclaimer for any reason.
	 *
	 * ^ Redistributions in binary form must reproduce the above copyright
	 * notice, this list of conditions and the following disclaimer in the
	 * documentation and/or other materials provided with the distribution.
	 *
	 * THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS
	 * IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
	 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
	 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
	 * OR COPYRIGHT HOLDERS OR CONTRIBUTORS  BE LIABLE FOR ANY CLAIM, DIRECT,
	 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
	 * OR OTHER LIABILITY,(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
	 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
	 * WHETHER AN ACTION OF IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
	 * NEGLIGENCE OR OTHERWISE) ARISING FROM, OUT OF, IN CONNECTION OR
	 * IN ANY OTHER WAY OUT OF THE USE OF OR OTHER DEALINGS WITH THIS
	 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	 */

	/**
	 * ...
	 * @author skyboy
	 */
	/**
	 * fastSort(*, uint);
	 * fastSort(*, String, uint);
	 *
	 * fastSort(vectorRef, &quot;z&quot;, Array.NUMERIC);
	 * @param	*: input	The object to be sorted. Either an Array, Vector, or any Object (or subclass of) that has a length property and numeric indicies
	 * @param	*: ...rest	The second parameter can either be options (pass in the same you would for Array's sort method) or a String to trigger sortOn functionality, the third should then be the options.
	 */
	public function fastSort(input:*, ...rest):void {
		if (!input || !(&quot;length&quot; in input) || !(input.length is int)) return;
		sortVec.length = 0;
		sortVec.length = input.length as uint;


		
		if (rest[0] is String) {
			if (!(rest[1] is Number)) rest[1] = 0;
			if (input is Array) {
				sortOnArray(input, rest[0], rest[1]);
			} else if (input is Vector.&lt;Number&gt;) {
				sortVecNumber.length = 0;
				sortVecNumber.length = input.length as uint;				
				sortOnVectorNumber(input, rest[0], rest[1]);
			} else if (input is Vector.&lt;int&gt;) {
				sortVecInt.length = 0;
				sortVecInt.length = input.length as uint;				
				sortOnVectorInt(input, rest[0], rest[1]);			
			} else if (input is Vector.&lt;uint&gt;) {
				sortVecUint.length = 0;
				sortVecUint.length = input.length as uint;				
				sortOnVectorUint(input, rest[0], rest[1]);					
			} else if (input is Vector.&lt;*&gt;) {
				sortOn(input, rest[0], rest[1]);
			} else {
				sortOnObject(input, rest[0], rest[1]);
			}
		} else {
			if (!(rest[0] is Number)) rest[0] = 0;
			if (input is Array) {
				sortArray(input, rest[0]);
			} else if (input is Vector.&lt;Number&gt; ) {
				sortVecNumber.length = 0;
				sortVecNumber.length = input.length as uint;	
				sortVectorNumber(input, rest[0]);
			} else if (input is Vector.&lt;int&gt; ) {
				sortVecInt.length = 0;
				sortVecInt.length = input.length as uint;	
				sortVectorInt(input, rest[0]);	
			} else if (input is Vector.&lt;uint&gt; ) {
				sortVecUint.length = 0;
				sortVecUint.length = input.length as uint;	
				sortVectorUint(input, rest[0]);					
			} else if (input is Vector.&lt;*&gt;) {
				sort(input, rest[0]);
			} else {
				sortObject(input, rest[0]);
			}
		}
	}
	
}
internal const NUMERIC:uint = Array.NUMERIC;
internal const DESCENDING:uint = Array.DESCENDING;
internal const CASEINSENSITIVE:uint = Array.CASEINSENSITIVE;
internal const sortVec:Vector.&lt;*&gt; = new Vector.&lt;*&gt;(0xFFFF); // reserve a large amount of space in memory for growth when sorting.
internal const sortVecNumber:Vector.&lt;Number&gt; = new Vector.&lt;Number&gt;(0); // reserve a large amount of space in memory for growth when sorting.
internal const sortVecInt:Vector.&lt;int&gt; = new Vector.&lt;int&gt;(0); // reserve a large amount of space in memory for growth when sorting.
internal const sortVecUint:Vector.&lt;uint&gt; = new Vector.&lt;uint&gt;(0); // reserve a large amount of space in memory for growth when sorting.

internal function quickSort(input:Vector.&lt;*&gt;, left:uint, right:uint, d:uint):void {
	if (right &gt;= input.length) right = input.length - 1;
	if (left &gt;= right) return;
	var j:uint = right, i:uint = left;
	var size:uint = right - left;
	var pivotPoint:* = input[(right + left) &gt;&gt;&gt; 1], t:*;
	do {
		if (size &lt; 9) {
			pivotPoint = input[left];
			do {
				do {
					++left;
					if (input[left] &lt; pivotPoint) {
						pivotPoint = input[left];
						do { // this section can be improved.
							input[left--] = input[left];
						} while (left &gt; i &amp;&amp; pivotPoint &lt; input[left]);
						input[left] = pivotPoint;
					}
				} while (left &lt; right);
				++i;
				left = i;
				pivotPoint = input[left];
			} while (i &lt; right);
			return;
		}
		while (left &lt; right) {
			if (input[right] &gt; pivotPoint) do { --right; } while (input[right] &gt; pivotPoint);
			if (input[left] &lt; pivotPoint) do { ++left; } while (input[left] &lt; pivotPoint);
			if (left &lt; right) {
				t = input[left];
				input[left] = input[right];
				input[right] = t;
				++left, --right;
			}
		}
		if (right) {
			if (left == right) {
				if (input[left] &lt; pivotPoint) ++left;
				else if (input[right] &gt; pivotPoint) --right;
			}
			if (i &lt; right) {
				quickSort(input, i, right, d + 1);
			}
		} else if (!left) left = 1;
		if (j &lt;= left) return;
		i = left;
		right = j;
		pivotPoint = input[(right + left) &gt;&gt;&gt; 1];
		size = right - left;
		++d;
	} while (true);
}
internal function quickSortOn(input:Vector.&lt;*&gt;, sInput:Vector.&lt;*&gt;, left:uint, right:uint, d:uint):void {
	var j:uint = right &gt;= input.length ? right = input.length - 1 : right;
	if (left &gt;= right) return;
	var i:uint = left;
	var size:uint = right - left;
	var pivotPoint:* = input[(right + left) &gt;&gt;&gt; 1], t:*;
	do {
		if (size &lt; 9) {
			do {
				pivotPoint = input[left];
				do {
					++left;
					if (pivotPoint &gt; input[left]) {
						pivotPoint = input[left];
						t = sInput[left];
						do {
							input[left] = input[left - 1];
							sInput[left] = sInput[--left];
						} while (left &gt; i &amp;&amp; pivotPoint &lt; input[left]);
						input[left] = pivotPoint;
						sInput[left] = t;
					}
				} while (left &lt; right);
				++i;
				left = i;
			} while (i &lt; right);
			return;
		}
		while (left &lt; right) {
			if (input[right] &gt; pivotPoint) do {
				--right;
			} while (input[right] &gt; pivotPoint);
			if (input[left] &lt; pivotPoint) do {
				++left;
			} while (input[left] &lt; pivotPoint);
			if (left &lt; right) {
				t = input[left];
				input[left] = input[right];
				input[right] = t;
				t = sInput[left];
				sInput[left] = sInput[right];
				sInput[right] = t;
				++left, --right;
			}
		}
		if (right) {
			if (left == right) {
				if (input[right] &gt; pivotPoint) --right;
				else if (input[left] &lt; pivotPoint) ++left;
				else ++left, --right;
			}
			if (i &lt; right) {
				quickSortOn(input, sInput, i, right, d + 1);
			}
		} else if (!left) left = 1;
		if (j &lt;= left) return;
		i = left;
		right = j;
		pivotPoint = input[(right + left) &gt;&gt;&gt; 1];
		size = right - left;
		++d;
	} while (true);
}
internal function quickSortArray(input:Array, left:uint, right:uint, d:uint):void {
	if (right &gt;= input.length) right = input.length - 1;
	if (left &gt;= right) return;
	var j:uint = right, i:uint = left;
	var size:uint = right - left;
	var pivotPoint:* = input[(right + left) &gt;&gt;&gt; 1], t:*;
	do {
		if (size &lt; 9) {
			pivotPoint = input[left];
			do {
				do {
					++left;
					if (input[left] &lt; pivotPoint) {
						pivotPoint = input[left];
						do { // this section can be improved.
							input[left--] = input[left];
						} while (left &gt; i &amp;&amp; pivotPoint &lt; input[left]);
						input[left] = pivotPoint;
					}
				} while (left &lt; right);
				++i;
				left = i;
				pivotPoint = input[left];
			} while (i &lt; right);
			return;
		}
		while (left &lt; right) {
			if (input[right] &gt; pivotPoint) do { --right; } while (input[right] &gt; pivotPoint);
			if (input[left] &lt; pivotPoint) do { ++left; } while (input[left] &lt; pivotPoint);
			if (left &lt; right) {
				t = input[left];
				input[left] = input[right];
				input[right] = t;
				++left, --right;
			}
		}
		if (right) {
			if (left == right) {
				if (input[left] &lt; pivotPoint) ++left;
				else if (input[right] &gt; pivotPoint) --right;
			}
			if (i &lt; right) {
				quickSortArray(input, i, right, d + 1);
			}
		} else if (!left) left = 1;
		if (j &lt;= left) return;
		i = left;
		right = j;
		pivotPoint = input[(right + left) &gt;&gt;&gt; 1];
		size = right - left;
		++d;
	} while (true);
}
internal function quickSortOnArray(input:Vector.&lt;*&gt;, sInput:Array, left:uint, right:uint, d:uint):void {
	var j:uint = right &gt;= input.length ? right = input.length - 1 : right;
	if (left &gt;= right) return;
	var i:uint = left;
	var size:uint = right - left;
	var pivotPoint:* = input[(right + left) &gt;&gt;&gt; 1], t:*;
	do {
		if (size &lt; 9) {
			do {
				pivotPoint = input[left];
				do {
					++left;
					if (pivotPoint &gt; input[left]) {
						pivotPoint = input[left];
						t = sInput[left];
						do {
							input[left] = input[left - 1];
							sInput[left] = sInput[--left];
						} while (left &gt; i &amp;&amp; pivotPoint &lt; input[left]);
						input[left] = pivotPoint;
						sInput[left] = t;
					}
				} while (left &lt; right);
				++i;
				left = i;
			} while (i &lt; right);
			return;
		}
		while (left &lt; right) {
			if (input[right] &gt; pivotPoint) do {
				--right;
			} while (input[right] &gt; pivotPoint);
			if (input[left] &lt; pivotPoint) do {
				++left;
			} while (input[left] &lt; pivotPoint);
			if (left &lt; right) {
				t = input[left];
				input[left] = input[right];
				input[right] = t;
				t = sInput[left];
				sInput[left] = sInput[right];
				sInput[right] = t;
				++left, --right;
			}
		}
		if (right) {
			if (left == right) {
				if (input[right] &gt; pivotPoint) --right;
				else if (input[left] &lt; pivotPoint) ++left;
				else ++left, --right;
			}
			if (i &lt; right) {
				quickSortOnArray(input, sInput, i, right, d + 1);
			}
		} else if (!left) left = 1;
		if (j &lt;= left) return;
		i = left;
		right = j;
		pivotPoint = input[(right + left) &gt;&gt;&gt; 1];
		size = right - left;
		++d;
	} while (true);
}
internal function quickSortObject(input:*, left:uint, right:uint, d:uint):void {
	if (right &gt;= input.length) right = input.length - 1;
	if (left &gt;= right) return;
	var j:uint = right, i:uint = left;
	var size:uint = right - left;
	var pivotPoint:* = input[(right + left) &gt;&gt;&gt; 1], t:*;
	do {
		if (size &lt; 9) {
			pivotPoint = input[left];
			do {
				do {
					++left;
					if (input[left] &lt; pivotPoint) {
						pivotPoint = input[left];
						do { // this section can be improved.
							input[left--] = input[left];
						} while (left &gt; i &amp;&amp; pivotPoint &lt; input[left]);
						input[left] = pivotPoint;
					}
				} while (left &lt; right);
				++i;
				left = i;
				pivotPoint = input[left];
			} while (i &lt; right);
			return;
		}
		while (left &lt; right) {
			if (input[right] &gt; pivotPoint) do { --right; } while (input[right] &gt; pivotPoint);
			if (input[left] &lt; pivotPoint) do { ++left; } while (input[left] &lt; pivotPoint);
			if (left &lt; right) {
				t = input[left];
				input[left] = input[right];
				input[right] = t;
				++left, --right;
			}
		}
		if (right) {
			if (left == right) {
				if (input[left] &lt; pivotPoint) ++left;
				else if (input[right] &gt; pivotPoint) --right;
			}
			if (i &lt; right) {
				quickSortObject(input, i, right, d + 1);
			}
		} else if (!left) left = 1;
		if (j &lt;= left) return;
		i = left;
		right = j;
		pivotPoint = input[(right + left) &gt;&gt;&gt; 1];
		size = right - left;
		++d;
	} while (true);
}
internal function quickSortOnObject(input:Vector.&lt;*&gt;, sInput:*, left:uint, right:uint, d:uint):void {
	var j:uint = right &gt;= input.length ? right = input.length - 1 : right;
	if (left &gt;= right) return;
	var i:uint = left;
	var size:uint = right - left;
	var pivotPoint:* = input[(right + left) &gt;&gt;&gt; 1], t:*;
	do {
		if (size &lt; 9) {
			do {
				pivotPoint = input[left];
				do {
					++left;
					if (pivotPoint &gt; input[left]) {
						pivotPoint = input[left];
						t = sInput[left];
						do {
							input[left] = input[left - 1];
							sInput[left] = sInput[--left];
						} while (left &gt; i &amp;&amp; pivotPoint &lt; input[left]);
						input[left] = pivotPoint;
						sInput[left] = t;
					}
				} while (left &lt; right);
				++i;
				left = i;
			} while (i &lt; right);
			return;
		}
		while (left &lt; right) {
			if (input[right] &gt; pivotPoint) do {
				--right;
			} while (input[right] &gt; pivotPoint);
			if (input[left] &lt; pivotPoint) do {
				++left;
			} while (input[left] &lt; pivotPoint);
			if (left &lt; right) {
				t = input[left];
				input[left] = input[right];
				input[right] = t;
				t = sInput[left];
				sInput[left] = sInput[right];
				sInput[right] = t;
				++left, --right;
			}
		}
		if (right) {
			if (left == right) {
				if (input[right] &gt; pivotPoint) --right;
				else if (input[left] &lt; pivotPoint) ++left;
				else ++left, --right;
			}
			if (i &lt; right) {
				quickSortOnObject(input, sInput, i, right, d + 1);
			}
		} else if (!left) left = 1;
		if (j &lt;= left) return;
		i = left;
		right = j;
		pivotPoint = input[(right + left) &gt;&gt;&gt; 1];
		size = right - left;
		++d;
	} while (true);
}
internal function sort(input:Vector.&lt;*&gt;, options:uint):void {
	var n:uint = input.length;
	if (n &lt; 2) return;
	var q:uint, left:uint, right:uint = n;
	var t:*;
	while (q != right) {
		t = input[q];
		if (t === undefined) {
			--right;
			input[q] = input[right];
			input[right] = undefined;
		} else if (t === null) {
			input[q] = input[left];
			input[left] = null;
			++left;
			++q;
		} else ++q;
	}
	if (right &gt; left) {
		q = left;
		while (q &lt; right) {
			t = input[q];
			if (t != t) {
				--right;
				input[q] = input[right];
				input[right] = NaN;
			} else ++q;
		}
		if (--right) {
			if (uint(right - 1) &gt; left) {
				if (options == NUMERIC) {
					quickSort(input, left, right, 0);
				} else {
					var tempVec:Vector.&lt;*&gt; = sortVec;
					q = right;
					if (!(options &amp; NUMERIC)) if (options &amp; CASEINSENSITIVE) {
						tempVec[q] = String(input[q]).toLowerCase();
						while (q-- &gt; left) tempVec[q] = String(input[q]).toLowerCase();
					} else {
						tempVec[q] = String(input[q]);
						while (q-- &gt; left) tempVec[q] = String(input[q]);
					}
					quickSortOn(tempVec, input, left, right, 0);
				}
			}
		}
	}
	if (options &amp; DESCENDING) {
		var i:uint = 0;
		while (n &lt; i) {
			t = input[i];
			input[i++] = input[--n];
			input[n] = t;
		}
	}
}
internal function sortOn(input:Vector.&lt;*&gt;, name:String, options:uint):void {
	var n:uint = input.length;
	if (n &lt; 2) return;
	var tempVec:Vector.&lt;*&gt; = sortVec, i:uint = n, t:*, j:uint = i;
	var left:uint, right:uint = i;
	while (j--) {
		t = input[j];
		t = name in t ? t[name] : t;
		if (t === null) {
			t = input[j];
			input[j] = input[left];
			input[left] = t;
			tempVec[left++] = null;
			++j;
		} else if (t === undefined) {
			if (--i != --right) {
				tempVec[i] = tempVec[right];
				tempVec[right] = undefined;
				t = input[right];
				input[right] = input[j];
				input[j] = t;
			}
		} else tempVec[--i] = t;
		if (j == left) break;
	}
	if (right &gt; left) {
		j = right;
		while (--j &gt; left) {
			t = tempVec[j];
			if (t != t) {
				if (j != --right) {
					tempVec[j] = tempVec[right];
					tempVec[right] = NaN;
					t = input[right];
					input[right] = input[j];
					input[j] = t;
				}
			}
		}
		if (--right) {
			if (uint(right - 1) &gt; left) {
				if (!(options &amp; NUMERIC)) {
					i = right;
					if (options &amp; CASEINSENSITIVE) {
						tempVec[i] = String(tempVec[i]).toUpperCase();
						while (i-- &gt; left) tempVec[i] = String(tempVec[i]).toUpperCase();
					} else {
						tempVec[i] = String(tempVec[i]);
						while (i-- &gt; left) tempVec[i] = String(tempVec[i]);
					}
				}
				quickSortOn(tempVec, input, left, right, 0);
			}
		}
	}
	if (options &amp; DESCENDING) {
		i = 0;
		while (n != i) {
			t = input[i];
			input[i++] = input[--n];
			input[n] = t;
		}
	}
}
internal function sortArray(input:Array, options:uint):void {
	var n:uint = input.length;
	if (n &lt; 2) return;
	var q:uint, left:uint, right:uint = n;
	var t:*;
	while (q != right) {
		t = input[q];
		if (t === undefined) {
			--right;
			input[q] = input[right];
			input[right] = undefined;
		} else if (t === null) {
			input[q] = input[left];
			input[left] = null;
			++left;
			++q;
		} else ++q;
	}
	if (right &gt; left) {
		q = left;
		while (q &lt; right) {
			t = input[q];
			if (t != t) {
				--right;
				input[q] = input[right];
				input[right] = NaN;
			} else ++q;
		}
		if (--right) {
			if (uint(right - 1) &gt; left) {
				if (options == NUMERIC) {
					quickSortArray(input, left, right, 0);
				} else {
					var tempVec:Vector.&lt;*&gt; = sortVec;
					q = right;
					if (!(options &amp; NUMERIC)) if (options &amp; CASEINSENSITIVE) {
						tempVec[q] = String(input[q]).toLowerCase();
						while (q-- &gt; left) tempVec[q] = String(input[q]).toLowerCase();
					} else {
						tempVec[q] = String(input[q]);
						while (q-- &gt; left) tempVec[q] = String(input[q]);
					}
					quickSortOnArray(tempVec, input, left, right, 0);
				}
			}
		}
	}
	if (options &amp; DESCENDING) {
		var i:uint = 0;
		while (n &lt; i) {
			t = input[i];
			input[i++] = input[--n];
			input[n] = t;
		}
	}
}
internal function sortOnArray(input:Array, name:String, options:uint):void {
	var n:uint = input.length;
	if (n &lt; 2) return;
	var tempVec:Vector.&lt;*&gt; = sortVec, i:uint = n, t:*, j:uint = i;
	var left:uint, right:uint = i;
	while (j--) {
		t = input[j];
		t = name in t ? t[name] : t;
		if (t === null) {
			t = input[j];
			input[j] = input[left];
			input[left] = t;
			tempVec[left++] = null;
			++j;
		} else if (t === undefined) {
			if (--i != --right) {
				tempVec[i] = tempVec[right];
				tempVec[right] = undefined;
				t = input[right];
				input[right] = input[j];
				input[j] = t;
			}
		} else tempVec[--i] = t;
		if (j == left) break;
	}
	if (right &gt; left) {
		j = right;
		while (--j &gt; left) {
			t = tempVec[j];
			if (t != t) {
				if (j != --right) {
					tempVec[j] = tempVec[right];
					tempVec[right] = NaN;
					t = input[right];
					input[right] = input[j];
					input[j] = t;
				}
			}
		}
		if (--right) {
			if (uint(right - 1) &gt; left) {
				if (!(options &amp; NUMERIC)) {
					i = right;
					if (options &amp; CASEINSENSITIVE) {
						tempVec[i] = String(tempVec[i]).toUpperCase();
						while (i-- &gt; left) tempVec[i] = String(tempVec[i]).toUpperCase();
					} else {
						tempVec[i] = String(tempVec[i]);
						while (i-- &gt; left) tempVec[i] = String(tempVec[i]);
					}
				}
				quickSortOnArray(tempVec, input, left, right, 0);
			}
		}
	}
	if (options &amp; DESCENDING) {
		i = 0;
		while (n &lt; i) {
			t = input[i];
			input[i++] = input[--n];
			input[n] = t;
		}
	}
}
internal function sortObject(input:*, options:uint):void {
	var n:uint = input.length;
	if (n &lt; 2) return;
	var q:uint, left:uint, right:uint = n;
	var t:*;
	while (q != right) {
		t = input[q];
		if (t === undefined) {
			--right;
			input[q] = input[right];
			input[right] = undefined;
		} else if (t === null) {
			input[q] = input[left];
			input[left] = null;
			++left;
			++q;
		} else ++q;
	}
	if (right &gt; left) {
		q = left;
		while (q &lt; right) {
			t = input[q];
			if (t != t) {
				--right;
				input[q] = input[right];
				input[right] = NaN;
			} else ++q;
		}
		if (--right) {
			if (uint(right - 1) &gt; left) {
				if (options == NUMERIC) {
					quickSortObject(input, left, right, 0);
				} else {
					var tempVec:Vector.&lt;*&gt; = sortVec;
					q = right;
					if (!(options &amp; NUMERIC)) if (options &amp; CASEINSENSITIVE) {
						tempVec[q] = String(input[q]).toLowerCase();
						while (q-- &gt; left) tempVec[q] = String(input[q]).toLowerCase();
					} else {
						tempVec[q] = String(input[q]);
						while (q-- &gt; left) tempVec[q] = String(input[q]);
					}
					quickSortOnObject(tempVec, input, left, right, 0);
				}
			}
		}
	}
	if (options &amp; DESCENDING) {
		var i:uint = 0;
		while (n &lt; i) {
			t = input[i];
			input[i++] = input[--n];
			input[n] = t;
		}
	}
}
internal function sortOnObject(input:*, name:String, options:uint):void {
	var n:uint = input.length;
	if (n &lt; 2) return;
	var tempVec:Vector.&lt;*&gt; = sortVec, i:uint = n, t:*, j:uint = i;
	var left:uint, right:uint = i;
	while (j--) {
		t = input[j];
		t = name in t ? t[name] : t;
		if (t === null) {
			t = input[j];
			input[j] = input[left];
			input[left] = t;
			tempVec[left++] = null;
			++j;
		} else if (t === undefined) {
			if (--i != --right) {
				tempVec[i] = tempVec[right];
				tempVec[right] = undefined;
				t = input[right];
				input[right] = input[j];
				input[j] = t;
			}
		} else tempVec[--i] = t;
		if (j == left) break;
	}
	if (right &gt; left) {
		j = right;
		while (--j &gt; left) {
			t = tempVec[j];
			if (t != t) {
				if (j != --right) {
					tempVec[j] = tempVec[right];
					tempVec[right] = NaN;
					t = input[right];
					input[right] = input[j];
					input[j] = t;
				}
			}
		}
		if (--right) {
			if (uint(right - 1) &gt; left) {
				if (!(options &amp; NUMERIC)) {
					i = right;
					if (options &amp; CASEINSENSITIVE) {
						tempVec[i] = String(tempVec[i]).toUpperCase();
						while (i-- &gt; left) tempVec[i] = String(tempVec[i]).toUpperCase();
					} else {
						tempVec[i] = String(tempVec[i]);
						while (i-- &gt; left) tempVec[i] = String(tempVec[i]);
					}
				}
				quickSortOnObject(tempVec, input, left, right, 0);
			}
		}
	}
	if (options &amp; DESCENDING) {
		i = 0;
		while (n &lt; i) {
			t = input[i];
			input[i++] = input[--n];
			input[n] = t;
		}
	}
}
	
internal function quickSortVectorNumber(input:Vector.&lt;Number&gt;, left:int, right:int, d:int):void {
	if (right &gt;= input.length) right = input.length - 1;
	if (left &gt;= right) return;
	var j:int = right, i:int = left;
	var size:int = right - left;
	var pivotPoint:Number = input[int((right + left) &gt;&gt;&gt; 1)], t:Number;
	do {
		if (size &lt; 9) {
			pivotPoint = input[int(left)];
			do {
				do {
					++left;
					if (input[int(left)] &lt; pivotPoint) {
						pivotPoint = input[int(left)];
						do { // this section can be improved.
							input[int(left--)] = input[int(left)];
						} while (left &gt; i &amp;&amp; pivotPoint &lt; input[int(left)]);
						input[int(left)] = pivotPoint;
					}
				} while (left &lt; right);
				++i;
				left = i;
				pivotPoint = input[int(left)];
			} while (i &lt; right);
			return;
		}
		while (left &lt; right) {
			if (input[int(right)] &gt; pivotPoint) do { --right; } while (input[int(right)] &gt; pivotPoint);
			if (input[int(left)] &lt; pivotPoint) do { ++left; } while (input[int(left)] &lt; pivotPoint);
			if (left &lt; right) {
				t = input[int(left)];
				input[int(left)] = input[int(right)];
				input[int(right)] = t;
				++left, --right;
			}
		}
		if (right) {
			if (left == right) {
				if (input[int(left)] &lt; pivotPoint) ++left;
				else if (input[int(right)] &gt; pivotPoint) --right;
			}
			if (i &lt; right) {
				quickSortVectorNumber(input, i, right, d + 1);
			}
		} else if (!left) left = 1;
		if (j &lt;= left) return;
		i = left;
		right = j;
		pivotPoint = input[int((right + left) &gt;&gt;&gt; 1)];
		size = right - left;
		++d;
	} while (true);
}
internal function quickSortOnVectorNumber(input:Vector.&lt;Number&gt;, sInput:Vector.&lt;Number&gt;, left:int, right:int, d:int):void {
	var j:int = 0;
	if (right &gt;= input.length)
	{
		j = right = input.length - 1;
	}
	else
	{
		right
	}

	if (left &gt;= right) return;
	var i:int = left;
	var size:int = right - left;
	var pivotPoint:Number = input[int((right + left) &gt;&gt;&gt; 1)], t:Number;
	do {
		if (size &lt; 9) {
			do {
				pivotPoint = input[int(left)];
				do {
					++left;
					if (pivotPoint &gt; input[int(left)]) {
						pivotPoint = input[int(left)];
						t = sInput[int(left)];
						do {
							input[int(left)] = input[int(left - 1)];
							sInput[int(left)] = sInput[int(--left)];
						} while (left &gt; i &amp;&amp; pivotPoint &lt; input[int(left)]);
						input[int(left)] = pivotPoint;
						sInput[int(left)] = t;
					}
				} while (left &lt; right);
				++i;
				left = i;
			} while (i &lt; right);
			return;
		}
		while (left &lt; right) {
			if (input[int(right)] &gt; pivotPoint) do {
				--right;
			} while (input[int(right)] &gt; pivotPoint);
			if (input[int(left)] &lt; pivotPoint) do {
				++left;
			} while (input[int(left)] &lt; pivotPoint);
			if (left &lt; right) {
				t = input[int(left)];
				input[int(left)] = input[int(right)];
				input[int(right)] = t;
				t = sInput[int(left)];
				sInput[int(left)] = sInput[int(right)];
				sInput[int(right)] = t;
				++left, --right;
			}
		}
		if (right) {
			if (left == right) {
				if (input[int(right)] &gt; pivotPoint) --right;
				else if (input[int(left)] &lt; pivotPoint) ++left;
				else ++left, --right;
			}
			if (i &lt; right) {
				quickSortOnVectorNumber(input, sInput, i, right, d + 1);
			}
		} else if (!left) left = 1;
		if (j &lt;= left) return;
		i = left;
		right = j;
		pivotPoint = input[int((right + left) &gt;&gt;&gt; 1)];
		size = right - left;
		++d;
	} while (true);
}
internal function sortVectorNumber(input:Vector.&lt;Number&gt;, options:int):void {
	var n:int = input.length;
	if (n &lt; 2) return;
	var q:int, left:int, right:int = n;
	var t:Number;
	q = right;

	if (right &gt; left) {
		q = left;
		while (q &lt; right) {
			t = input[int(q)];
			if (t != t) {
				--right;
				input[int(q)] = input[int(right)];
				input[int(right)] = NaN;
			} else ++q;
		}
		if (--right) {
			if (int(right - 1) &gt; left) {
				quickSortVectorNumber(input, left, right, 0);
			}
		}
	}
	if (options &amp; Array.DESCENDING) {
		var i:int = 0;
		while (n &lt; i) {
			t = input[int(i)];
			input[int(i++)] = input[int(--n)];
			input[int(n)] = t;
		}
	}
	}
internal function sortOnVectorNumber(input:Vector.&lt;Number&gt;, name:String, options:int):void {
		var n:int = input.length;
		if (n &lt; 2) return;
		var tempVec:Vector.&lt;Number&gt; = sortVecNumber, i:int = n, t:Number, j:int = i;
		var left:int, right:int = i;
		while (j--) {
			t = input[int(j)];
			t = name in t ? t[name] : t;
			tempVec[int(--i)] = t;
			if (j == left) break;
		}
		if (right &gt; left) {
			j = right;
			while (--j &gt; left) {
				t = tempVec[int(j)];
				if (t != t) {
					if (j != --right) {
						tempVec[int(j)] = tempVec[int(right)];
						tempVec[int(right)] = NaN;
						t = input[int(right)];
						input[int(right)] = input[int(j)];
						input[int(j)] = t;
					}
				}
			}
			if (--right) {
				if (int(right - 1) &gt; left) {
					quickSortOnVectorNumber(tempVec, input, left, right, 0);
				}
			}
		}
		if (options &amp; Array.DESCENDING) {
			i = 0;
			while (n != i) {
				t = input[int(i)];
				input[int(i++)] = input[int(--n)];
				input[int(n)] = t;
			}
		}	
	}


internal function quickSortVectorInt(input:Vector.&lt;int&gt;, left:int, right:int, d:int):void {
	if (right &gt;= input.length) right = input.length - 1;
	if (left &gt;= right) return;
	var j:int = right, i:int = left;
	var size:int = right - left;
	var pivotPoint:int = input[int((right + left) &gt;&gt;&gt; 1)], t:int;
	do {
		if (size &lt; 9) {
			pivotPoint = input[int(left)];
			do {
				do {
					++left;
					if (input[int(left)] &lt; pivotPoint) {
						pivotPoint = input[int(left)];
						do { // this section can be improved.
							input[int(left--)] = input[int(left)];
						} while (left &gt; i &amp;&amp; pivotPoint &lt; input[int(left)]);
						input[int(left)] = pivotPoint;
					}
				} while (left &lt; right);
				++i;
				left = i;
				pivotPoint = input[int(left)];
			} while (i &lt; right);
			return;
		}
		while (left &lt; right) {
			if (input[int(right)] &gt; pivotPoint) do { --right; } while (input[int(right)] &gt; pivotPoint);
			if (input[int(left)] &lt; pivotPoint) do { ++left; } while (input[int(left)] &lt; pivotPoint);
			if (left &lt; right) {
				t = input[int(left)];
				input[int(left)] = input[int(right)];
				input[int(right)] = t;
				++left, --right;
			}
		}
		if (right) {
			if (left == right) {
				if (input[int(left)] &lt; pivotPoint) ++left;
				else if (input[int(right)] &gt; pivotPoint) --right;
			}
			if (i &lt; right) {
				quickSortVectorInt(input, i, right, d + 1);
			}
		} else if (!left) left = 1;
		if (j &lt;= left) return;
		i = left;
		right = j;
		pivotPoint = input[int((right + left) &gt;&gt;&gt; 1)];
		size = right - left;
		++d;
	} while (true);
}
internal function quickSortOnVectorInt(input:Vector.&lt;int&gt;, sInput:Vector.&lt;int&gt;, left:int, right:int, d:int):void {
	var j:int = 0;
	if (right &gt;= input.length)
	{
		j = right = input.length - 1;
	}
	else
	{
		right
	}

	if (left &gt;= right) return;
	var i:int = left;
	var size:int = right - left;
	var pivotPoint:int = input[int((right + left) &gt;&gt;&gt; 1)], t:int;
	do {
		if (size &lt; 9) {
			do {
				pivotPoint = input[int(left)];
				do {
					++left;
					if (pivotPoint &gt; input[int(left)]) {
						pivotPoint = input[int(left)];
						t = sInput[int(left)];
						do {
							input[int(left)] = input[int(left - 1)];
							sInput[int(left)] = sInput[int(--left)];
						} while (left &gt; i &amp;&amp; pivotPoint &lt; input[int(left)]);
						input[int(left)] = pivotPoint;
						sInput[int(left)] = t;
					}
				} while (left &lt; right);
				++i;
				left = i;
			} while (i &lt; right);
			return;
		}
		while (left &lt; right) {
			if (input[int(right)] &gt; pivotPoint) do {
				--right;
			} while (input[int(right)] &gt; pivotPoint);
			if (input[int(left)] &lt; pivotPoint) do {
				++left;
			} while (input[int(left)] &lt; pivotPoint);
			if (left &lt; right) {
				t = input[int(left)];
				input[int(left)] = input[int(right)];
				input[int(right)] = t;
				t = sInput[int(left)];
				sInput[int(left)] = sInput[int(right)];
				sInput[int(right)] = t;
				++left, --right;
			}
		}
		if (right) {
			if (left == right) {
				if (input[int(right)] &gt; pivotPoint) --right;
				else if (input[int(left)] &lt; pivotPoint) ++left;
				else ++left, --right;
			}
			if (i &lt; right) {
				quickSortOnVectorInt(input, sInput, i, right, d + 1);
			}
		} else if (!left) left = 1;
		if (j &lt;= left) return;
		i = left;
		right = j;
		pivotPoint = input[int((right + left) &gt;&gt;&gt; 1)];
		size = right - left;
		++d;
	} while (true);
}
internal function sortVectorInt(input:Vector.&lt;int&gt;, options:int):void {
	var n:int = input.length;
	if (n &lt; 2) return;
	var q:int, left:int, right:int = n;
	var t:int;
	q = right;

	if (right &gt; left) {
		q = left;
		while (q &lt; right) {
			t = input[int(q)];
			if (t != t) {
				--right;
				input[int(q)] = input[int(right)];
				input[int(right)] = NaN;
			} else ++q;
		}
		if (--right) {
			if (int(right - 1) &gt; left) {
				quickSortVectorInt(input, left, right, 0);
			}
		}
	}
	if (options &amp; Array.DESCENDING) {
		var i:int = 0;
		while (n &lt; i) {
			t = input[int(i)];
			input[int(i++)] = input[int(--n)];
			input[int(n)] = t;
		}
	}
	}
internal function sortOnVectorInt(input:Vector.&lt;int&gt;, name:String, options:int):void {
		var n:int = input.length;
		if (n &lt; 2) return;
		var tempVec:Vector.&lt;int&gt; = sortVecInt, i:int = n, t:int, j:int = i;
		var left:int, right:int = i;
		while (j--) {
			t = input[int(j)];
			t = name in t ? t[name] : t;
			tempVec[int(--i)] = t;
			if (j == left) break;
		}
		if (right &gt; left) {
			j = right;
			while (--j &gt; left) {
				t = tempVec[int(j)];
				if (t != t) {
					if (j != --right) {
						tempVec[int(j)] = tempVec[int(right)];
						tempVec[int(right)] = NaN;
						t = input[int(right)];
						input[int(right)] = input[int(j)];
						input[int(j)] = t;
					}
				}
			}
			if (--right) {
				if (int(right - 1) &gt; left) {
					quickSortOnVectorInt(tempVec, input, left, right, 0);
				}
			}
		}
		if (options &amp; Array.DESCENDING) {
			i = 0;
			while (n != i) {
				t = input[int(i)];
				input[int(i++)] = input[int(--n)];
				input[int(n)] = t;
			}
		}	
	}


internal function quickSortVectorUint(input:Vector.&lt;uint&gt;, left:int, right:int, d:int):void {
	if (right &gt;= input.length) right = input.length - 1;
	if (left &gt;= right) return;
	var j:int = right, i:int = left;
	var size:int = right - left;
	var pivotPoint:uint = input[int((right + left) &gt;&gt;&gt; 1)], t:uint;
	do {
		if (size &lt; 9) {
			pivotPoint = input[int(left)];
			do {
				do {
					++left;
					if (input[int(left)] &lt; pivotPoint) {
						pivotPoint = input[int(left)];
						do { // this section can be improved.
							input[int(left--)] = input[int(left)];
						} while (left &gt; i &amp;&amp; pivotPoint &lt; input[int(left)]);
						input[int(left)] = pivotPoint;
					}
				} while (left &lt; right);
				++i;
				left = i;
				pivotPoint = input[int(left)];
			} while (i &lt; right);
			return;
		}
		while (left &lt; right) {
			if (input[int(right)] &gt; pivotPoint) do { --right; } while (input[int(right)] &gt; pivotPoint);
			if (input[int(left)] &lt; pivotPoint) do { ++left; } while (input[int(left)] &lt; pivotPoint);
			if (left &lt; right) {
				t = input[int(left)];
				input[int(left)] = input[int(right)];
				input[int(right)] = t;
				++left, --right;
			}
		}
		if (right) {
			if (left == right) {
				if (input[int(left)] &lt; pivotPoint) ++left;
				else if (input[int(right)] &gt; pivotPoint) --right;
			}
			if (i &lt; right) {
				quickSortVectorUint(input, i, right, d + 1);
			}
		} else if (!left) left = 1;
		if (j &lt;= left) return;
		i = left;
		right = j;
		pivotPoint = input[int((right + left) &gt;&gt;&gt; 1)];
		size = right - left;
		++d;
	} while (true);
}
internal function quickSortOnVectorUint(input:Vector.&lt;uint&gt;, sInput:Vector.&lt;uint&gt;, left:int, right:int, d:int):void {
	var j:int = 0;
	if (right &gt;= input.length)
	{
		j = right = input.length - 1;
	}
	else
	{
		right
	}

	if (left &gt;= right) return;
	var i:int = left;
	var size:int = right - left;
	var pivotPoint:uint = input[int((right + left) &gt;&gt;&gt; 1)], t:uint;
	do {
		if (size &lt; 9) {
			do {
				pivotPoint = input[int(left)];
				do {
					++left;
					if (pivotPoint &gt; input[int(left)]) {
						pivotPoint = input[int(left)];
						t = sInput[int(left)];
						do {
							input[int(left)] = input[int(left - 1)];
							sInput[int(left)] = sInput[int(--left)];
						} while (left &gt; i &amp;&amp; pivotPoint &lt; input[int(left)]);
						input[int(left)] = pivotPoint;
						sInput[int(left)] = t;
					}
				} while (left &lt; right);
				++i;
				left = i;
			} while (i &lt; right);
			return;
		}
		while (left &lt; right) {
			if (input[int(right)] &gt; pivotPoint) do {
				--right;
			} while (input[int(right)] &gt; pivotPoint);
			if (input[int(left)] &lt; pivotPoint) do {
				++left;
			} while (input[int(left)] &lt; pivotPoint);
			if (left &lt; right) {
				t = input[int(left)];
				input[int(left)] = input[int(right)];
				input[int(right)] = t;
				t = sInput[int(left)];
				sInput[int(left)] = sInput[int(right)];
				sInput[int(right)] = t;
				++left, --right;
			}
		}
		if (right) {
			if (left == right) {
				if (input[int(right)] &gt; pivotPoint) --right;
				else if (input[int(left)] &lt; pivotPoint) ++left;
				else ++left, --right;
			}
			if (i &lt; right) {
				quickSortOnVectorUint(input, sInput, i, right, d + 1);
			}
		} else if (!left) left = 1;
		if (j &lt;= left) return;
		i = left;
		right = j;
		pivotPoint = input[int((right + left) &gt;&gt;&gt; 1)];
		size = right - left;
		++d;
	} while (true);
}
internal function sortVectorUint(input:Vector.&lt;uint&gt;, options:int):void {
	var n:int = input.length;
	if (n &lt; 2) return;
	var q:int, left:int, right:int = n;
	var t:uint;
	q = right;

	if (right &gt; left) {
		q = left;
		while (q &lt; right) {
			t = input[int(q)];
			if (t != t) {
				--right;
				input[int(q)] = input[int(right)];
				input[int(right)] = NaN;
			} else ++q;
		}
		if (--right) {
			if (int(right - 1) &gt; left) {
				quickSortVectorUint(input, left, right, 0);
			}
		}
	}
	if (options &amp; Array.DESCENDING) {
		var i:int = 0;
		while (n &lt; i) {
			t = input[int(i)];
			input[int(i++)] = input[int(--n)];
			input[int(n)] = t;
		}
	}
	}
internal function sortOnVectorUint(input:Vector.&lt;uint&gt;, name:String, options:int):void {
	var n:int = input.length;
	if (n &lt; 2) return;
	var tempVec:Vector.&lt;uint&gt; = sortVecUint, i:int = n, t:uint, j:int = i;
	var left:int, right:int = i;
	while (j--) {
		t = input[int(j)];
		t = name in t ? t[name] : t;
		tempVec[int(--i)] = t;
		if (j == left) break;
	}
	if (right &gt; left) {
		j = right;
		while (--j &gt; left) {
			t = tempVec[int(j)];
			if (t != t) {
				if (j != --right) {
					tempVec[int(j)] = tempVec[int(right)];
					tempVec[int(right)] = NaN;
					t = input[int(right)];
					input[int(right)] = input[int(j)];
					input[int(j)] = t;
				}
			}
		}
		if (--right) {
			if (int(right - 1) &gt; left) {
				quickSortOnVectorUint(tempVec, input, left, right, 0);
			}
		}
	}
	if (options &amp; Array.DESCENDING) {
		i = 0;
		while (n != i) {
			t = input[int(i)];
			input[int(i++)] = input[int(--n)];
			input[int(n)] = t;
		}
	}	
}
</pre></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jpauclair.wordpress.com/825/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jpauclair.wordpress.com/825/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jpauclair.wordpress.com/825/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jpauclair.wordpress.com/825/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jpauclair.wordpress.com/825/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jpauclair.wordpress.com/825/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jpauclair.wordpress.com/825/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jpauclair.wordpress.com/825/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jpauclair.wordpress.com/825/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jpauclair.wordpress.com/825/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jpauclair.wordpress.com/825/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jpauclair.wordpress.com/825/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jpauclair.wordpress.com/825/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jpauclair.wordpress.com/825/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=825&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jpauclair.net/2012/03/12/fastsort-faster-is-better/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/ff60a0adbbe0ae671125435044931eb1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jpauclair</media:title>
		</media:content>
	</item>
		<item>
		<title>Epic Flash memory leak track down</title>
		<link>http://jpauclair.net/2012/02/25/epic-memory-track-down/</link>
		<comments>http://jpauclair.net/2012/02/25/epic-memory-track-down/#comments</comments>
		<pubDate>Sun, 26 Feb 2012 03:31:15 +0000</pubDate>
		<dc:creator>jpauclair</dc:creator>
				<category><![CDATA[actionscript]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[general]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[avm2]]></category>
		<category><![CDATA[bytecode]]></category>
		<category><![CDATA[haxe]]></category>
		<category><![CDATA[jit]]></category>
		<category><![CDATA[nape]]></category>
		<category><![CDATA[tamarin]]></category>

		<guid isPermaLink="false">http://jpauclair.net/?p=807</guid>
		<description><![CDATA[Have you ever had a memory instantiation problem that was impossible to track down? Here is a post that might help you with that kind of thing! Beware! This post is very long&#8230; but VERY instructive! If you want to learn some internal mechanism of Flash, I strongly suggest you read it from top to [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=807&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Have you ever had a memory instantiation problem that was <strong>impossible to track down</strong>? Here is a post that might help you with that kind of thing!</p>
<p><strong>Beware</strong>! This post is very long&#8230; but VERY instructive! If you want to learn some internal mechanism of Flash, I strongly suggest you read it from top to bottom without skipping parts!:)</p>
<p>After finding what it was, we can conclude that this is not a real leak but a irritating behaviour of the Flash VM.  Still, you should all be aware of it!</p>
<h2>The Context</h2>
<p>Yesterday I was helping Luca (creator of <strong><a href="http://code.google.com/p/nape/" title="Nape">Nape</a> physic engine, </strong>made with<strong> <a href="http://haxe.org/" title="haXe">haXe</a></strong>) to find what seemed to be a big memory leak. There was a couple framework used so it could be directly from Nape&#8230; or from <strong><a href="http://starling-framework.org/" title="Starling">Starling</a></strong>&#8230; or from debug tool running&#8230; or from a port error from haXe&#8230;</p>
<p><a href="http://jpauclair.files.wordpress.com/2012/02/memory.png"><img src="http://jpauclair.files.wordpress.com/2012/02/memory.png?w=497" alt="" title="memory"   class="aligncenter size-full wp-image-811" /></a></p>
<h2>So I though it was going to be simple</h2>
<p><span id="more-807"></span><br />
I got <strong><a href="http://www.sociodox.com/theminer/" title="TheMiner">TheMiner</a></strong> running and started profiling. It was pretty easy to find a LOT of memory allocation coming from Starling. The SWC version available is over 4 months old and back then there was a lot of useless instantiation coming from <a href="https://github.com/PrimaryFeather/Starling-Framework/blob/cda629986341e2ca6bb2239f39bb132545529dda/starling/src/starling/events/TouchProcessor.as" title="TouchProcessor">TouchProcessor.as</a><br />
If you use Starling, I suggest you build from sources as these instantiation are gone now.<br />
There are a couple left but no big deal.</p>
<p>We also saw that Nape was using a LOT of <strong>anonymous function call</strong> and some <strong>try catch</strong>. This create what’s called <strong>activation-object</strong>. And there was a lot of these. So by removing anon-calls and try catch we were able to remove a lot of instanciation.</p>
<p>And After removing the debugging tools, It was clear it was coming from haXe or Nape.</p>
<p>But even when <a href="http://www.sociodox.com/theminer/feature.html#instantiationRaw" title="Instantiation Raw Data Dump">recording all samples</a> allocated by the VM I could not find the damn allocation. (we are talking of more than 1Mo per sec)</p>
<p>Then I wrote a <strong><a href="http://code.google.com/p/apparat/" title="Scala">Scala</a></strong> script to try to identify samples that could have been missed, but that didn’t help me much since that was only an override of <strong>constructor</strong> and <strong>constructorProp</strong> avm opcodes.</p>
<h2>Simplifying the context</h2>
<p>So I decided to look a bit further into the bytecode and found something very interesting.</p>
<p>After simplifying the problem multiple time, I got this very simple code to demonstrate the bug.<br />
Because Nape has that very nice <strong>abstraction layer</strong>, it can support both standard DisplayObject as well as Starling 3D DisplayObject.</p>
<p>The leak happens when Nape try to set the DisplayObject properties like .x, .y, .rotation, etc.<br />
Let’s create a fake DisplayObject class and name it DO</p>
<p><pre class="brush: as3;">
public class DO
{
	public var x:Number;
	public var y:Number;

	public function DO() { }
}
</pre></p>
<p>And now, a simple loop that set .x and .y values on that DisplayObject, and on a UnTyped object representing the abstraction layer.</p>
<p><pre class="brush: as3;">
public class MainBug extends Sprite {
	public var mAnonDO:*;
	public var mDO:DO;
	public function MainBug():void {
			mDO = new DO();
			mAnonDO = mDO;
			addEventListener(Event.ENTER_FRAME, update);
		}
		public function update(ev:Event):void {
			var j:Number = 234.3948;
			for (var i:int = 0; i &lt; 1000; i++) {
			mDO.x     = j; // &lt;-- memory is flat
			mAnonDO.y = j; // &lt;-- causes memory to explode
		}
	}
}
</pre></p>
<p>So basicly we have the same DO Object in memory, and we access it via a Typed or an UnTyped variable.<br />
When accessing it with the Typed on, nothing happens, The memory is not impacted at all.<br />
But when accessing through the Anonymous Object, <strong>BAM, 1 Mo/sec</strong>. wtf?</p>
<h2>The ByteCode:</h2>
<p>So let’s take a look at the bytecode generated for this loop in the update() function:</p>
<p><pre class="brush: as3;">
while(int1 &lt; 1000)
{
	    #16   label
	
	    #18   getlocal0
	    #19   getproperty  mDO
	    #20   getlocal2
	    #21   setproperty  x
	this.mDO.x = number1;
	
	    #23   getlocal0
	    #24   getproperty  mAnonDO
	    #25   getlocal2
	    #26   setproperty  y
	this.mAnonDO.y = number1;
	
	    #28   getlocal3
	    #29   increment_i
	    #30   convert_i
	    #31   setlocal3
	int1 = int(int1) + 1;
}
</pre></p>
<p>I don’t know if you see any difference between the Anonymous function and the strickly typed one, but for me they look pretty much the same! <strong>getlocal0, getProp, getlocal2, setProp</strong>.</p>
<p>Again, when we comment out “<strong>this.mDO.x = number1;</strong>“, there is a lot of memory allocation, and when we comment out the other one “<strong>this.mAnonDO.y = number1;</strong>” there is <strong>zero allocation</strong>.</p>
<h2>A strange behaviour</h2>
<p>So if it’s not in the opcodes&#8230; it’s deeper! For those who have read the AVM2 Architecture documentation, you might remember that after the opcodes there are still a big phase to go through: <strong>The JIT, including Intermediate representation, and Machine Code Assembly</strong>.</p>
<p><a href="http://jpauclair.files.wordpress.com/2012/02/avm2architecture.png"><img src="http://jpauclair.files.wordpress.com/2012/02/avm2architecture.png?w=497&h=435" alt="" title="avm2Architecture" width="497" height="435" class="aligncenter size-full wp-image-809" /></a></p>
<h1>Intermediate representation (MIR)</h1>
<p>As demonstrated in the graph, the intermediate representation is part of the JIT.<br />
And it looks pretty much like this:<br />
<a href="http://jpauclair.files.wordpress.com/2012/02/codeflow.png"><img src="http://jpauclair.files.wordpress.com/2012/02/codeflow.png?w=497&h=435" alt="" title="CodeFlow" width="497" height="435" class="aligncenter size-full wp-image-810" /></a><br />
When the <strong>abc</strong> is ready to be processed, the JIT compiles it in the <strong>MIR</strong>, and then the result is process for your specific machine (Win32, MAX, Linux, etc.) in a Machine Dependant Code.</p>
<p>To find that damn memory leak, I had to output that MIR code.</p>
<h1>Digging deeper (The MIR)!</h1>
<p>So I decided to go back in time to an old post I made about tracing Assembly data generated by the JIT: <a href="http://jpauclair.net/2010/03/15/flash-asm/">Flash Assembler (not ByteCode) : And you thought it couldn’t get faster/</a></p>
<p>I don’t use this function a lot nowadays because it has been <strong>removed from all FlashPlayer</strong> build since Flash 10.1</p>
<p>But it is possible to output it in old version of the player!</p>
<p>Here is the output for the strictly typed part:</p>
<p><pre class="brush: plain;">

40:getlocal0
	@83 use   @16 [0]
		stack: MainBug?@83
		locals: MainBug?@83 flash.events::Event?@21 Number@60 int@67
41:getproperty mDO
	cse   @75
	@84 ucmp  @83 @75
	@85 jeq   @84 -&gt; 0
	@86 ld    132(@83)
		stack: DO?@86
		locals: MainBug@83 flash.events::Event?@21 Number@60 int@67
43:getlocal2
	@87 fuse  @60 [2]
		stack: DO?@86 Number@87
		locals: MainBug@83 flash.events::Event?@21 Number@87 int@67
44:setproperty x
	cse   @75
	@88 ucmp  @86 @75
	@89 jeq   @88 -&gt; 0
	@90 st    24(@86) &lt;- @87
		stack:
		locals: MainBug@83 flash.events::Event?@21 Number@87 int@67

</pre></p>
<p>And here is the output for the <strong>not</strong> strictly typed part:</p>
<p><pre class="brush: plain;">

48:getlocal0
	 @94 use   @16 [0]
		 stack: MainBug@94
		 locals: MainBug@94 flash.events::Event?@21 Number@60 int@67
 49:getproperty mAnonDO
	 @95 ld    128(@94)
		 stack: *@95
		 locals: MainBug@94 flash.events::Event?@21 Number@60 int@67
 51:getlocal2
	 @96 fuse  @60 [2]
		 stack: *@95 Number@96
		 locals: MainBug@94 flash.events::Event?@21 Number@96 int@67
 52:setproperty {MainBug,public,MainBug.as$29}::y
	 save state
	 @97 def   @95
	 @98 fdef  @96
	 @99 cm    MethodEnv::nullcheck (@3, @95)
	 set code context
	 @101 st    43382752(0) &lt;- @3
	 set dxns addr
	 @102 ldop  0(@3)
	 @103 ldop  20(@102)
	 @104 lea   4(@103)
	 @105 st    43382076(0) &lt;- @104
	 @106 fuse  @98 [6]
	 cse   @78
	 @107 cmop  AvmCore::doubleToAtom_sse2 (@78, @106)
	 init multiname
	 @109 alloc 16
	 @110 imm   16
	 @111 st    0(@109) &lt;- @110
	 @112 imm   43427168
	 @113 st    4(@109) &lt;- @112
	 @114 imm   44102088
	 @115 st    8(@109) &lt;- @114
	 cse   @102
	 @116 ldop  8(@102)
	 @117 use   @97 [5]
	 @118 cmop  Toplevel::toVTable (@116, @117)
	 cse   @102
	 cse   @116
	 @120 lea   0(@109)
	 save state
	 @121 cm    Toplevel::setproperty (@116, @117, @120, @107, @118)
		 stack:
		 locals: MainBug@16 flash.events::Event?@21 Number@60 int@67

</pre></p>
<p>Whoa!!<br />
What the hell is that!</p>
<p>It’s the same setproperty opcode, but with a LOT of things underneath&#8230;</p>
<p>The difference is really that one variable is strictly typed, and the other not.</p>
<p>We can see it on the Stack:<br />
<pre class="brush: plain;">
stack: DO?@86 Number@87
</pre></p>
<p>vs</p>
<p><pre class="brush: plain;">
stack: *@95 Number@96
</pre></p>
<p>No need to say that just by looking at the number of instructions, you KNOW it will be a <strong>lot slower</strong>.<br />
But not only that.. you can see <strong>type validation</strong>, <strong>memory allocation</strong> (   @109 alloc 16 )<br />
and even access to the <strong>VTable</strong>:       @118 cmop  Toplevel::toVTable (@116, @117)</p>
<p>So I though *<strong>bingo</strong>*, there is our allocation!</p>
<h2>*sight*&#8230; It&#8217;s not over yet!</h2>
<p>I knew that the memory growing was <strong>not a problem when using Int</strong> instead of Number.<br />
So I tried to output the same MIR code for the Int test:</p>
<p><pre class="brush: plain;">
43:getlocal2
	@88 use   @62 [2]
		stack: *@87 int@88
		locals: Main@84 flash.events::Event?@21 int@88 int@69
44:setproperty {Main,.events:EventDispatcher}::x
	save state
	@89 def   @87
	@90 def   @88
	@91 cm    MethodEnv::nullcheck (@3, @87)
	set code context
	@93 st    39909344(0) &amp;lt;- @3
	set dxns addr
	@94 ldop  0(@3)
	@95 ldop  20(@94)
	@96 lea   4(@95)
	@97 st    39908668(0) &amp;lt;- @96
	@98 use   @90 [6]
	cse   @79
	@99 cmop  AvmCore::intToAtom (@79, @98)
	init multiname
	@101 alloc 16
	@102 imm   16
	@103 st    0(@101) &amp;lt;- @102
	@104 imm   39953728
	@105 st    4(@101) &amp;lt;- @104
	@106 imm   40632776
	@107 st    8(@101) &amp;lt;- @106
	cse   @94
	@108 ldop  8(@94)
	@109 use   @89 [5]
	@110 cmop  Toplevel::toVTable (@108, @109)
	cse   @94
	cse   @108
	@112 lea   0(@101)
</pre><br />
Again&#8230;. it looks pretty much the same <img src='http://s0.wp.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<p>..So it’s not the Alloc from the MIR code that create the memory.</p>
<p>What difference is there left? Well on one side you have:<br />
<pre class="brush: plain;">
@99 cmop  AvmCore::intToAtom (@79, @98)
</pre><br />
and on the other side you have:<br />
<pre class="brush: plain;">
@107 cmop  AvmCore::doubleToAtom_sse2 (@78, @106)
</pre></p>
<p>Could it be directly from Tamarin? Let’s open some code!</p>
<h2>Digging even Deeper (<a href="https://developer.mozilla.org/en/Tamarin" title="Tamarin">Tamarin</a> Core)!</h2>
<p>Let’s start with <strong>intToAtom</strong>:<br />
<pre class="brush: cpp;">
Atom AvmCore::intToAtom(int n)
{
	// handle integer values w/out allocation
	int i29 = n &amp;lt;&amp;lt; 3;
	if ((i29&amp;gt;&amp;gt;3) == n)
	{
		return uint32(i29 | kIntegerType);;
	}
	else
	{
		return allocDouble(n);
	}
}
</pre></p>
<p>Interesting&#8230; I always like the feeling of viewing Alloc in a line of code.</p>
<p>So I remembered that <strong>Int atom was encoded with only 29 bits</strong> for the value. I changed my test and instead of</p>
<p><pre class="brush: cpp;">
var j:int = 234;
</pre></p>
<p>I used</p>
<p><pre class="brush: cpp;">
var j:int = int.MAX_VALUE;
</pre></p>
<p>and <strong>BAM AGAIN</strong>!<br />
memory growing like crazy.</p>
<p>Ok so I guess we are getting a lot closer to the source now.</p>
<p>Here is the <strong>doubleToAtom_sse2 </strong>function:</p>
<p>doubleToAtom_sse2 is defined in the <strong>AvmCore.cpp</strong> class from Tamarin</p>
<p><pre class="brush: cpp;">
Atom AvmCore::doubleToAtom_sse2(double n)
{
	 int id3;
	 _asm {
			 movsd xmm0,n
			 cvttsd2si ecx,xmm0
			 shl ecx,3               // id&lt;&lt;3
			 mov eax,ecx
			 sar ecx,3               // id&gt;&gt;3
			 cvtsi2sd xmm1,ecx
			 ucomisd xmm0,xmm1
			 jne d2a_alloc   // &lt; or &gt;
			 jp  d2a_alloc   // unordered
			 mov id3,eax
	}

	if (id3 != 0 || !MathUtils::isNegZero(n))
	{
		 return id3 | kIntegerType;
	}
	else
	{
		 _asm d2a_alloc:
		 return allocDouble(n);
	}
}
</pre></p>
<p>Again, you can see the allocDouble in there.<br />
But you can also see the <strong>return integer Atom</strong> part!<br />
Again I forgot about that! <strong>dynamic type switching from int to number.. but also from number to int!</strong></p>
<p>I re-wrote the test to use</p>
<p><pre class="brush: as3;">
var j:Number = 234.3948;
</pre></p>
<p>and used</p>
<p><pre class="brush: as3;">
var j:Number = 234;
</pre></p>
<p>And&#8230; here we go again&#8230; <strong>zero instantiation</strong>!</p>
<p>I guess the only thing left to look at is the <strong>allocDouble</strong>() function right?</p>
<p>Here it is:</p>
<p><pre class="brush: cpp;">
Atom allocDouble(double n)
{
	double *ptr = (double*)GetGC()-&amp;gt;Alloc(sizeof(double), 0);
	*ptr = n;
	return kDoubleType | (uintptr)ptr;
}
</pre></p>
<p>Oh my! look at that! <strong>A call to allocate the memory</strong> for a double!</p>
<h1>Conclusion</h1>
<p>At runtime, when you use anonymous object, the JIT have no idea of what type it is, and when you need to set the property on one of these object, it need to validate the objects, and instantiate a new Atom to copy the values.<br />
It’s not the case when you use strictly typed object because when it’s ready to set the value, it just does!</p>
<p>When putting all the elements together you get this ridiculous code:</p>
<p><pre class="brush: as3;">
var anon:*;
for (var i:int = 0; i &amp;lt; 100000; i++) {
	anon = 3.3;
}
</pre></p>
<p>This will allocate memory <strong>like crazy</strong>. (100000 * sizeof(double) )</p>
<p><a href="http://jpauclair.files.wordpress.com/2012/02/memorydance.png"><img src="http://jpauclair.files.wordpress.com/2012/02/memorydance.png?w=497" alt="" title="MemoryDance"   class="aligncenter size-full wp-image-812" /></a></p>
<p>If you think this is a bug, <a href="https://bugbase.adobe.com/index.cfm?event=bug&amp;id=3123526" title="Memory grow bug">vote for it</a></p>
<h1>Solutions?</h1>
<p>I didn’t find any great way to solve this problem except from using strictly typed object.</p>
<p>Going back to <strong>Nape</strong>, it means that it cannot use the abstraction layer like it was designed.<br />
The only way is to expose a generic management for classic displayobject, and overridable functions to give the possibility to an external framework (like Starling) to do updates of properties in a strictly typed way.</p>
<h1>References:</h1>
<p><strong>Frameworks:</strong><br />
<a href="http://starling-framework.org/">http://starling-framework.org/</a><br />
<a href="https://github.com/PrimaryFeather/Starling-Framework/blob/master/starling/src/starling/events/TouchProcessor.as">https://github.com/PrimaryFeather/Starling-Framework/blob/master/starling/src/starling/events/TouchProcessor.as</a><br />
<a href="http://code.google.com/p/nape/">http://code.google.com/p/nape/</a><br />
<strong>Tool:</strong><br />
<a href="http://code.google.com/p/apparat/">http://code.google.com/p/apparat/</a><br />
<a href="http://www.sociodox.com/theminer/">http://www.sociodox.com/theminer/</a><br />
<strong>Docs:</strong><br />
<a href="http://www.adobe.com/content/dam/Adobe/en/devnet/actionscript/articles/avm2overview.pdf">http://www.adobe.com/content/dam/Adobe/en/devnet/actionscript/articles/avm2overview.pdf</a><br />
<a href="http://onflex.org/ACDS/AS3TuningInsideAVM2JIT.pdf">http://onflex.org/ACDS/AS3TuningInsideAVM2JIT.pdf</a><br />
<a href="http://zenit.senecac.on.ca/wiki/dxr/source.cgi/mozilla/js/tamarin/core/AvmCore.cpp">http://zenit.senecac.on.ca/wiki/dxr/source.cgi/mozilla/js/tamarin/core/AvmCore.cpp</a><br />
<a href="http://zenit.senecac.on.ca/wiki/dxr/source.cgi/mozilla/js/tamarin/core/AvmCore.h">http://zenit.senecac.on.ca/wiki/dxr/source.cgi/mozilla/js/tamarin/core/AvmCore.h</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jpauclair.wordpress.com/807/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jpauclair.wordpress.com/807/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jpauclair.wordpress.com/807/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jpauclair.wordpress.com/807/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jpauclair.wordpress.com/807/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jpauclair.wordpress.com/807/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jpauclair.wordpress.com/807/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jpauclair.wordpress.com/807/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jpauclair.wordpress.com/807/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jpauclair.wordpress.com/807/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jpauclair.wordpress.com/807/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jpauclair.wordpress.com/807/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jpauclair.wordpress.com/807/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jpauclair.wordpress.com/807/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=807&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jpauclair.net/2012/02/25/epic-memory-track-down/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/ff60a0adbbe0ae671125435044931eb1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jpauclair</media:title>
		</media:content>

		<media:content url="http://jpauclair.files.wordpress.com/2012/02/memory.png" medium="image">
			<media:title type="html">memory</media:title>
		</media:content>

		<media:content url="http://jpauclair.files.wordpress.com/2012/02/avm2architecture.png" medium="image">
			<media:title type="html">avm2Architecture</media:title>
		</media:content>

		<media:content url="http://jpauclair.files.wordpress.com/2012/02/codeflow.png" medium="image">
			<media:title type="html">CodeFlow</media:title>
		</media:content>

		<media:content url="http://jpauclair.files.wordpress.com/2012/02/memorydance.png" medium="image">
			<media:title type="html">MemoryDance</media:title>
		</media:content>
	</item>
		<item>
		<title>Updated the optimized Base64 library</title>
		<link>http://jpauclair.net/2012/01/12/updated-the-optimized-bas64-library/</link>
		<comments>http://jpauclair.net/2012/01/12/updated-the-optimized-bas64-library/#comments</comments>
		<pubDate>Fri, 13 Jan 2012 02:35:06 +0000</pubDate>
		<dc:creator>jpauclair</dc:creator>
				<category><![CDATA[actionscript]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[general]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[base64]]></category>
		<category><![CDATA[haxe]]></category>
		<category><![CDATA[opcodes]]></category>
		<category><![CDATA[swcs]]></category>

		<guid isPermaLink="false">http://jpauclair.net/?p=766</guid>
		<description><![CDATA[More than two years ago, I made a blog post about how to optimized the existing Base64 libraries. This library was highly linked and used in multiple project as it&#8217;s 100% free (MIT license) A few days ago I decided to take another look at it just for fun. To see if I could get [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=766&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>More than two years ago, I made a <a title="Base64 blog post" href="http://jpauclair.net/2010/01/09/base64-optimized-as3-lib/">blog post</a> about how to optimized the existing Base64 libraries.</p>
<p>This library was highly linked and used in multiple project as it&#8217;s 100% free (MIT license)</p>
<p>A few days ago I decided to take another look at it just for fun. To see if I could get it to be a bit faster.</p>
<p>Here is some change I made to make it even faster:<br />
<span id="more-766"></span><br />
On of the biggest change was to go from bytearray.writeInt() to direct byte access bytearray[]</p>
<h2><strong>Optimizing the old version</strong></h2>
<p><pre class="brush: as3;">

//BEFORE

c = data[i++] &lt;&lt; 16 | data[i++] &lt;&lt; 8 | data[i++];

c = (_encodeChars[c &gt;&gt;&gt; 18] &lt;&lt; 24) | (_encodeChars[c &gt;&gt;&gt; 12 &amp; 0x3f] &lt;&lt; 16) | (_encodeChars[c &gt;&gt;&gt; 6 &amp; 0x3f] &lt;&lt; 8 ) | _encodeChars[c &amp; 0x3f];

 out.writeInt(c);

//AFTER

c = data[int(i++)] &lt;&lt; 16 | data[int(i++)] &lt;&lt; 8 | data[int(i++)];

 out[int(outPos++)] = _encodeChars[int(c &gt;&gt;&gt; 18)];
 out[int(outPos++)] = _encodeChars[int(c &gt;&gt;&gt; 12 &amp; 0x3f)];
 out[int(outPos++)] = _encodeChars[int(c &gt;&gt;&gt; 6 &amp; 0x3f)];
 out[int(outPos++)] = _encodeChars[int(c &amp; 0x3f)];
</pre></p>
<p>You can also see the explicit int cast for all bytearray access. It does not always make a big difference, but depending on debug/release runtime and code, it can help a bit.</p>
<p>Another thing I change is the handling of &#8220;invalid&#8221; base 64 data.</p>
<p>When decoding a base 64 string, one of the high-cost operation was validation.</p>
<p>By removing validation of invalid data, it made the code 30% faster.</p>
<p>While I understand that validation is important in many case, having a ultra-fast library is also important for many developper.</p>
<h2><strong>Why not using Azoth, haXe or Alchemy SWCs</strong></h2>
<p>Well I could.</p>
<p>The problem is that right now they all use the fast-memory opcodes that won&#8217;t be supported for FlashPlayer 11.2 and upper.</p>
<p>This mean that any application that was build with libraries likes theses won&#8217;t be able to run in the future &#8220;as-is&#8221;</p>
<p>Hence, having a native-as3 library with sources that you can edit is very important.</p>
<p>&nbsp;</p>
<h2><strong>The Result:</strong></h2>
<p>Grab the full source, please go and take it on this site:</p>
<p><a href="http://www.sociodox.com/base64.html">http://www.sociodox.com/base64.html</a></p>
<p>and here:</p>
<p><pre class="brush: as3;">
/*
 * Copyright (C) 2012 Jean-Philippe Auclair
 * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
 * Base64 library for ActionScript 3.0.
 * By: Jean-Philippe Auclair : http://jpauclair.net
 * Based on article: http://jpauclair.net/2010/01/09/base64-optimized-as3-lib/
 * Benchmark:
 * This version: encode: 260ms decode: 255ms
 * Blog version: encode: 322ms decode: 694ms
 * as3Crypto encode: 6728ms decode: 4098ms
 *
 * Encode: com.sociodox.utils.Base64 is 25.8x faster than as3Crypto Base64
 * Decode: com.sociodox.utils.Base64 is 16x faster than as3Crypto Base64
 *
 * Optimize &amp; Profile any Flash content with TheMiner ( http://www.sociodox.com/theminer )
 */
package com.sociodox.utils
{
 import flash.utils.ByteArray;
 public class Base64
 {
 private static const _encodeChars:Vector.&lt;int&gt; = InitEncoreChar();
 private static const _decodeChars:Vector.&lt;int&gt; = InitDecodeChar();

 public static function encode(data:ByteArray):String
 {
 var out:ByteArray = new ByteArray();
 //Presetting the length keep the memory smaller and optimize speed since there is no &quot;grow&quot; needed
 out.length = (2 + data.length - ((data.length + 2) % 3)) * 4 / 3; //Preset length //1.6 to 1.5 ms
 var i:int = 0;
 var r:int = data.length % 3;
 var len:int = data.length - r;
 var c:uint; //read (3) character AND write (4) characters
 var outPos:int=0;
 while (i &lt; len)
 {
 //Read 3 Characters (8bit * 3 = 24 bits)
 c = data[int(i++)] &lt;&lt; 16 | data[int(i++)] &lt;&lt; 8 | data[int(i++)];

 out[int(outPos++)] = _encodeChars[int(c &gt;&gt;&gt; 18)];
 out[int(outPos++)] = _encodeChars[int(c &gt;&gt;&gt; 12 &amp; 0x3f)];
 out[int(outPos++)] = _encodeChars[int(c &gt;&gt;&gt; 6 &amp; 0x3f)];
 out[int(outPos++)] = _encodeChars[int(c &amp; 0x3f)];
 }

 if (r == 1) //Need two &quot;=&quot; padding
 {
 //Read one char, write two chars, write padding
 c = data[int(i)];

out[int(outPos++)] = _encodeChars[int(c &gt;&gt;&gt; 2)];
 out[int(outPos++)] = _encodeChars[int((c &amp; 0x03) &lt;&lt; 4)];
 out[int(outPos++)] = 61;
 out[int(outPos++)] = 61;
 }
 else if (r == 2) //Need one &quot;=&quot; padding
 {
 c = data[int(i++)] &lt;&lt; 8 | data[int(i)];

out[int(outPos++)] = _encodeChars[int(c &gt;&gt;&gt; 10)];
 out[int(outPos++)] = _encodeChars[int(c &gt;&gt;&gt; 4 &amp; 0x3f)];
 out[int(outPos++)] = _encodeChars[int((c &amp; 0x0f) &lt;&lt; 2)];
 out[int(outPos++)] = 61;
 }

return out.readUTFBytes(out.length);
 }


 public static function decode(str:String):ByteArray
 {
 var c1:int;
 var c2:int;
 var c3:int;
 var c4:int;
 var i:int = 0;
 var len:int = str.length;

var byteString:ByteArray = new ByteArray();
 byteString.writeUTFBytes(str);
 var outPos:int = 0;
 while (i &lt; len)
 {
 //c1
 c1 = _decodeChars[int(byteString[i++])];
 if (c1 == -1) break;

 //c2
 c2 = _decodeChars[int(byteString[i++])];
 if (c2 == -1) break;

 byteString[int(outPos++)] = (c1 &lt;&lt; 2) | ((c2 &amp; 0x30) &gt;&gt; 4);

 //c3
 c3 = byteString[int(i++)];
 if (c3 == 61)
 {
 byteString.length = outPos
 return byteString;
 }

 c3 = _decodeChars[int(c3)];
 if (c3 == -1) break;

 byteString[int(outPos++)] = ((c2 &amp; 0x0f) &lt;&lt; 4) | ((c3 &amp; 0x3c) &gt;&gt; 2);

 //c4
 c4 = byteString[int(i++)];
 if (c4 == 61)
 {
 byteString.length = outPos
 return byteString;
 }

 c4 = _decodeChars[int(c4)];
 if (c4 == -1) break;

 byteString[int(outPos++)] = ((c3 &amp; 0x03) &lt;&lt; 6) | c4;
 }
 byteString.length = outPos
 return byteString;
 }

 public static function InitEncoreChar() : Vector.&lt;int&gt;
 {
 var encodeChars:Vector.&lt;int&gt; = new Vector.&lt;int&gt;(64,true);

 // We could push the number directly, but i think it's nice to see the characters (with no overhead on encode/decode)
 var chars:String = &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&quot;;
 for (var i:int = 0; i &lt; 64; i++)
 {
 encodeChars[i] = chars.charCodeAt(i);
 }

return encodeChars;
 }

public static function InitDecodeChar():Vector.&lt;int&gt;
{

var decodeChars:Vector.&lt;int&gt; = new &lt;int&gt;[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1];

return decodeChars;
}

 }
}

</pre></p>
<p>If you have any trick to make this faster, please post a comment!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jpauclair.wordpress.com/766/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jpauclair.wordpress.com/766/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jpauclair.wordpress.com/766/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jpauclair.wordpress.com/766/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jpauclair.wordpress.com/766/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jpauclair.wordpress.com/766/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jpauclair.wordpress.com/766/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jpauclair.wordpress.com/766/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jpauclair.wordpress.com/766/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jpauclair.wordpress.com/766/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jpauclair.wordpress.com/766/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jpauclair.wordpress.com/766/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jpauclair.wordpress.com/766/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jpauclair.wordpress.com/766/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=766&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jpauclair.net/2012/01/12/updated-the-optimized-bas64-library/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/ff60a0adbbe0ae671125435044931eb1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jpauclair</media:title>
		</media:content>
	</item>
		<item>
		<title>Be an affiliate Miner!</title>
		<link>http://jpauclair.net/2012/01/12/be-an-affiliate-miner/</link>
		<comments>http://jpauclair.net/2012/01/12/be-an-affiliate-miner/#comments</comments>
		<pubDate>Fri, 13 Jan 2012 00:47:58 +0000</pubDate>
		<dc:creator>jpauclair</dc:creator>
				<category><![CDATA[general]]></category>

		<guid isPermaLink="false">http://jpauclair.net/?p=762</guid>
		<description><![CDATA[I just wanted to let you know that TheMiner remain 100% free for all non-commercial use, but if you like the product and you want to help promote TheMiner, you can become a sale affiliate very easily! It&#8217;s simple as: -Put TheMiner icon on your website.. or blog.. or forum.. car painting.. cat clothes.. -Earn [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=762&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I just wanted to let you know that TheMiner remain 100% free for all non-commercial use, but if you like the product and you want to help promote TheMiner, you can become a sale affiliate very easily!<br />
It&#8217;s simple as:<br />
-Put TheMiner icon on your website.. or blog.. or forum.. car painting.. cat clothes..<br />
-Earn money if people click and buy the PRO version of this awesome software.</p>
<p><a title="Affiliate Sales" href="http://secure.plimus.com/jsp/developer_login.jsp?affReqId=14F789E6249EE5A2"><img class="aligncenter size-full wp-image-701" title="MinerIconBanner" src="http://jpauclair.files.wordpress.com/2011/12/minericonbanner.png?w=497" alt=""   /></a></p>
<h2 style="text-align:center;"><a title="Affiliate Sales" href="http://secure.plimus.com/jsp/developer_login.jsp?affReqId=14F789E6249EE5A2">I want to be a sale affiliate</a></h2>
<p>&nbsp;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jpauclair.wordpress.com/762/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jpauclair.wordpress.com/762/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jpauclair.wordpress.com/762/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jpauclair.wordpress.com/762/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jpauclair.wordpress.com/762/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jpauclair.wordpress.com/762/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jpauclair.wordpress.com/762/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jpauclair.wordpress.com/762/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jpauclair.wordpress.com/762/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jpauclair.wordpress.com/762/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jpauclair.wordpress.com/762/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jpauclair.wordpress.com/762/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jpauclair.wordpress.com/762/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jpauclair.wordpress.com/762/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=762&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jpauclair.net/2012/01/12/be-an-affiliate-miner/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/ff60a0adbbe0ae671125435044931eb1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jpauclair</media:title>
		</media:content>

		<media:content url="http://jpauclair.files.wordpress.com/2011/12/minericonbanner.png" medium="image">
			<media:title type="html">MinerIconBanner</media:title>
		</media:content>
	</item>
		<item>
		<title>Got Bugs? We got the bugbase!</title>
		<link>http://jpauclair.net/2011/12/15/got-bugs-we-got-the-bugbase/</link>
		<comments>http://jpauclair.net/2011/12/15/got-bugs-we-got-the-bugbase/#comments</comments>
		<pubDate>Thu, 15 Dec 2011 23:38:28 +0000</pubDate>
		<dc:creator>jpauclair</dc:creator>
				<category><![CDATA[general]]></category>

		<guid isPermaLink="false">http://jpauclair.net/?p=756</guid>
		<description><![CDATA[We just added a Mantis BugBase for TheMiner. It&#8217;s a full anonymous access, so everyone is welcome to report TheMiner bugs to make sure they are going to be fixed quickly! Thanks to everybody for making this such a great collaborative project! &#160; TheMiner BugBase TheMiner Home Page<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=756&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>We just added a Mantis BugBase for TheMiner.</p>
<p>It&#8217;s a full anonymous access, so everyone is welcome to report TheMiner bugs to make sure they are going to be fixed quickly!</p>
<p>Thanks to everybody for making this such a great collaborative project!</p>
<p><a title="Sociodox - TheMiner" href="http://www.sociodox.com/theminer"><img class="size-full wp-image-703 alignleft" title="MinerIconWeb" src="http://jpauclair.files.wordpress.com/2011/12/minericonweb.png?w=497" alt=""   /></a></p>
<p>&nbsp;</p>
<p><a title="TheMiner BugBase" href="http://www.sociodox.com/TheMinerBugBase/">TheMiner BugBase</a></p>
<p><a title="Sociodox - TheMiner" href="http://www.sociodox.com/theminer">TheMiner Home Page</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jpauclair.wordpress.com/756/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jpauclair.wordpress.com/756/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jpauclair.wordpress.com/756/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jpauclair.wordpress.com/756/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jpauclair.wordpress.com/756/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jpauclair.wordpress.com/756/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jpauclair.wordpress.com/756/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jpauclair.wordpress.com/756/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jpauclair.wordpress.com/756/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jpauclair.wordpress.com/756/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jpauclair.wordpress.com/756/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jpauclair.wordpress.com/756/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jpauclair.wordpress.com/756/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jpauclair.wordpress.com/756/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=756&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jpauclair.net/2011/12/15/got-bugs-we-got-the-bugbase/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/ff60a0adbbe0ae671125435044931eb1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jpauclair</media:title>
		</media:content>

		<media:content url="http://jpauclair.files.wordpress.com/2011/12/minericonweb.png" medium="image">
			<media:title type="html">MinerIconWeb</media:title>
		</media:content>
	</item>
		<item>
		<title>The king is dead. Long live the king!</title>
		<link>http://jpauclair.net/2011/12/12/the-king-is-dead-long-live-the-king/</link>
		<comments>http://jpauclair.net/2011/12/12/the-king-is-dead-long-live-the-king/#comments</comments>
		<pubDate>Mon, 12 Dec 2011 23:42:17 +0000</pubDate>
		<dc:creator>jpauclair</dc:creator>
				<category><![CDATA[actionscript]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[general]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[profiling]]></category>

		<guid isPermaLink="false">http://jpauclair.net/?p=698</guid>
		<description><![CDATA[The king is dead: Yes.. today I have some bad new for you. One of the best flash performance analysis tool: FlashPreloadProfiler, is officialy dead. After a LOT of time developing this profiler for flash. I decided to kill the thing. Long live the king! YES! After this much effort, it would be too sad [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=698&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h3>The king is dead:</h3>
<p>Yes.. today I have some bad new for you. One of the best <strong>flash performance analysis tool</strong>: FlashPreloadProfiler, is officialy dead. After a LOT of time developing this profiler for flash. I decided to kill the thing.</p>
<h3>Long live the king!</h3>
<p style="text-align:left;">YES! After this much effort, it would be too sad to drop everything. right?<br />
Launching today, TheMiner is the new (<strong>FLash Profiling</strong>) solution that will take the place of FlashPreloadProfiler, but with a lot of optimization, innovation and new features!<br />
TheMiner is dedicated to every single hard-working developer that are making the most out of what they have by analysing and improving flash application. Every hardcore developer should be proud to be a miner and has such, we decided to make it look like a hero worker.<br />
<strong></strong></p>
<p style="text-align:center;"><strong>You ARE TheMiner(s)</strong><br />
<a href="http://www.sociodox.com/theminer"><img class="aligncenter size-full wp-image-712" title="Miner" src="http://jpauclair.files.wordpress.com/2011/12/miner.png?w=497" alt=""   /></a></p>
<p>TheMiner is now part of another entity called Sociodox <a href="http://www.sociodox.com/theminer"><img class="alignright size-full wp-image-708" title="sociodox" src="http://jpauclair.files.wordpress.com/2011/12/sociodox.png?w=497" alt=""   /></a><br />
The main website as also moved to a new address: <a title="Sociodox - TheMiner" href="http://www.sociodox.com/theminer">http://www.sociodox.com/theminer</a></p>
<h3></h3>
<h3>PROMOTION:</h3>
<p>TheMiner is now free for any non-commercial use</p>
<p>cost a little something for commercial use.</p>
<p>Let&#8217;s <strong>give-away</strong> a couple <strong>COUPON</strong> for TheMiner Pro</p>
<ol>
<li>&#8221; IAmTheFirstMiner &#8221; : 75% off for the first 3 ppl to buy it!</li>
<li>&#8220; 0DayCoder &#8221; : 20% off for the first 20 ppl to buy it!</li>
<li>&#8220; HappyBugFreeChristmas &#8221; : 12% , Everyone deserve a christmas gift!</li>
<li>&#8221; jpauclair.net &#8221; : You love my blog? Have some percent.</li>
<li>&#8221; flashpreloadprofiler &#8221; : For the good old time.</li>
</ol>
<h4>You are a blogger? You have a website? Talk about TheMiner or Link to it with TheMiner icons, send me the link and get 50% off!</h4>
<h3>History: from FlashPreloadProfiler to TheMiner</h3>
<p><pre class="brush: as3;">
/////////////////////////
// Added:
//
// One frame Trace of all methods with arguments, file and line.
// DebugTexture to see stretch,smoothing, and color variation
// Minimize
// a QUIT button when profiler is minimed
// FPS and Mem in the top bar
// Screen Capture (save to file)
// Pause interface in Performance &amp; Memory profiler
// Filter in Memory profiler
// Filter in Function profiler
// Filter in Loader profiler
// Filter for file errors in loaders
// Start Off (off by default)
// MouseListener sprites
// Usage reporting (Google Analytics)
// Interlaced DataDump feature
// Visual feedback in memorygraph showing GC time and weight (gray bar)
// GC indicator in Flash Statistics
// Auto-check update when opening configuration panel
// Low process when everything off
// Skin Loading / Saving
// Flash Player Version in Stats tab
// Added a &quot;Already Collected&quot; column to Memory dump
// Stage Resolution in FlashStats

/////////////////////////
// Fixed:
//
// wrong DataDump sampling recording status
// bad colors for invisible object in Overdraw
// bad opacity management of selection highlights
// bad priority of preloader (over anything on stage)
// bad instanciation for air project
// Config are save automaticly when changed
// Now using latest version of MonsterDebugger (v3.1)
// Loader copy text not always working
// Loader won't show url of stream/loader on error
// MonsterDebuggerIcon needed tooltip.
// multiple TheMiner classes instanciation inside reports.
// multiple TheMiner self sampling in dump

/////////////////////////
// Optimized:
//
// a LOT the main loop, now should be pretty smooth to record samples
// Huge Rendering optimization in overdraw graph
// Huge Rendering optimization in LifeCycle graph
// Icons management
// Made the bar and spacing a bit smaller
</pre></p>
<h3>Localized:</h3>
<p>TheMiner has also been translated by the community in 8 languages:</p>
<p>English, French, Russian, Dutch, Spanish, Hindi, Chinese Traditional/Simplified</p>
<p>These ports are inside each build.</p>
<h3></h3>
<h3>More:</h3>
<p>TheMiner also come with more support:</p>
<p>A dedicated user group, a whole website with FAQ, support, installation help and more.</p>
<p>14 complete tutorials on how to use most of the features</p>
<h3>Are you a fan? Show your love!</h3>
<p>If you were already using FlashPreloadProfiler and you liked it,<br />
or if you now like TheMiner.<br />
Show your love on your site or anywhere else with these icons:<br />
<a href="http://jpauclair.files.wordpress.com/2011/12/minericonweb.png"><img class="aligncenter size-full wp-image-703" title="MinerIconWeb" src="http://jpauclair.files.wordpress.com/2011/12/minericonweb.png?w=497" alt=""   /></a></p>
<p><a href="http://jpauclair.files.wordpress.com/2011/12/minericonbe.png"><img class="aligncenter size-full wp-image-702" title="MinerIconBe" src="http://jpauclair.files.wordpress.com/2011/12/minericonbe.png?w=497" alt=""   /></a></p>
<p><a href="http://jpauclair.files.wordpress.com/2011/12/minericonbanner.png"><img class="aligncenter size-full wp-image-701" title="MinerIconBanner" src="http://jpauclair.files.wordpress.com/2011/12/minericonbanner.png?w=497" alt=""   /></a></p>
<h2>Downloads:</h2>
<h3><a href="http://www.sociodox.com/theminer">TheMiner </a>on <a href="http://www.sociodox.com/theminer">Sociodox </a>website</h3>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jpauclair.wordpress.com/698/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jpauclair.wordpress.com/698/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jpauclair.wordpress.com/698/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jpauclair.wordpress.com/698/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jpauclair.wordpress.com/698/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jpauclair.wordpress.com/698/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jpauclair.wordpress.com/698/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jpauclair.wordpress.com/698/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jpauclair.wordpress.com/698/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jpauclair.wordpress.com/698/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jpauclair.wordpress.com/698/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jpauclair.wordpress.com/698/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jpauclair.wordpress.com/698/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jpauclair.wordpress.com/698/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=698&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jpauclair.net/2011/12/12/the-king-is-dead-long-live-the-king/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/ff60a0adbbe0ae671125435044931eb1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jpauclair</media:title>
		</media:content>

		<media:content url="http://jpauclair.files.wordpress.com/2011/12/miner.png" medium="image">
			<media:title type="html">Miner</media:title>
		</media:content>

		<media:content url="http://jpauclair.files.wordpress.com/2011/12/sociodox.png" medium="image">
			<media:title type="html">sociodox</media:title>
		</media:content>

		<media:content url="http://jpauclair.files.wordpress.com/2011/12/minericonweb.png" medium="image">
			<media:title type="html">MinerIconWeb</media:title>
		</media:content>

		<media:content url="http://jpauclair.files.wordpress.com/2011/12/minericonbe.png" medium="image">
			<media:title type="html">MinerIconBe</media:title>
		</media:content>

		<media:content url="http://jpauclair.files.wordpress.com/2011/12/minericonbanner.png" medium="image">
			<media:title type="html">MinerIconBanner</media:title>
		</media:content>
	</item>
		<item>
		<title>Session Sneak Peek #2!</title>
		<link>http://jpauclair.net/2011/10/03/session-sneak-peek-2/</link>
		<comments>http://jpauclair.net/2011/10/03/session-sneak-peek-2/#comments</comments>
		<pubDate>Mon, 03 Oct 2011 23:59:27 +0000</pubDate>
		<dc:creator>jpauclair</dc:creator>
				<category><![CDATA[3D]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[general]]></category>
		<category><![CDATA[3d]]></category>
		<category><![CDATA[molehill]]></category>

		<guid isPermaLink="false">http://jpauclair.net/?p=681</guid>
		<description><![CDATA[The Session Here is Second Sneak peek of our sessions &#8220;Next-generation games using Stage3D(Molehill)&#8221; (Part 1 &#38; 2) at Adobe MAX Here is the first sneak peek The videos are in HD, watch them in full res!<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=681&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h2>The Session</h2>
<p>Here is Second Sneak peek of our sessions &#8220;Next-generation games using Stage3D(Molehill)&#8221; (Part 1 &amp; 2) at Adobe MAX</p>
<p><a href="http://wp.me/pImhf-aS" title="Session Sneak Peek #1">Here is the first sneak peek</a></p>
<p>The videos are in HD, watch them in full res!</p>
<p><a href="http://www.youtube.com/watch?v=CeYCsBIK3uE"><span style="text-align:center; display: block;"><a href="http://jpauclair.net/2011/10/03/session-sneak-peek-2/"><img src="http://img.youtube.com/vi/CeYCsBIK3uE/2.jpg" alt="" /></a></span></a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jpauclair.wordpress.com/681/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jpauclair.wordpress.com/681/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jpauclair.wordpress.com/681/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jpauclair.wordpress.com/681/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jpauclair.wordpress.com/681/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jpauclair.wordpress.com/681/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jpauclair.wordpress.com/681/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jpauclair.wordpress.com/681/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jpauclair.wordpress.com/681/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jpauclair.wordpress.com/681/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jpauclair.wordpress.com/681/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jpauclair.wordpress.com/681/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jpauclair.wordpress.com/681/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jpauclair.wordpress.com/681/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=681&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jpauclair.net/2011/10/03/session-sneak-peek-2/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/ff60a0adbbe0ae671125435044931eb1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jpauclair</media:title>
		</media:content>
	</item>
		<item>
		<title>Flash11 Session Sneak Peak</title>
		<link>http://jpauclair.net/2011/09/27/flash11-session-sneak-peak/</link>
		<comments>http://jpauclair.net/2011/09/27/flash11-session-sneak-peak/#comments</comments>
		<pubDate>Tue, 27 Sep 2011 14:17:02 +0000</pubDate>
		<dc:creator>jpauclair</dc:creator>
				<category><![CDATA[general]]></category>

		<guid isPermaLink="false">http://jpauclair.net/?p=674</guid>
		<description><![CDATA[The Session Here is Sneak peek of my session &#8220;Next-generation games using Stage3D(Molehill)&#8221; at Adobe MAX My friend [Jean-Philippe Doiron] and I will introduce multiple techniques such as deferred lighting, CascadeShadow Mapping, ScreenSpace Ambient occlusion, MRT, and more through vertex and fragment shaders. We will also show new ways of handling Physics, particles and pathfinding. [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=674&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h2>The Session</h2>
<p>Here is Sneak peek of my session &#8220;Next-generation games using Stage3D(Molehill)&#8221; at Adobe MAX</p>
<p>My friend [Jean-Philippe Doiron] and I will introduce multiple techniques such as deferred lighting, CascadeShadow Mapping, ScreenSpace Ambient occlusion, MRT, and more through vertex and fragment shaders. We will also show new ways of handling Physics, particles and pathfinding.</p>
<p>It&#8217;s a deep dive into GPU/CPU programming with the new Flash Player, and discover how to produce beautiful GPU effects that are reusable in your games and applications.</p>
<p>Please take a look at some of the things we are about to show you at the MAX!</p>
<h2>Video Sneak Peak</h2>
<p>The videos are in HD, watch them in full res!</p>
<p><a href="http://www.youtube.com/watch?v=vt29QBr_QXA"><span style="text-align:center; display: block;"><a href="http://jpauclair.net/2011/09/27/flash11-session-sneak-peak/"><img src="http://img.youtube.com/vi/vt29QBr_QXA/2.jpg" alt="" /></a></span></a></p>
<p><a href="http://www.youtube.com/watch?v=H22gIOpZArQ"><span style="text-align:center; display: block;"><a href="http://jpauclair.net/2011/09/27/flash11-session-sneak-peak/"><img src="http://img.youtube.com/vi/H22gIOpZArQ/2.jpg" alt="" /></a></span></a></p>
<p>Please register at AdobeMax and join the session : <a title="AdobeMax Session" href="http://bit.ly/odwg8U">http://bit.ly/odwg8U</a></p>
<p>We will also do a session on Flash3D at GDC Online if you can come: <a title="GDC Online Session" href="http://twb.io/n5rXxy">http://twb.io/n5rXxy</a></p>
<p>See you all there!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jpauclair.wordpress.com/674/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jpauclair.wordpress.com/674/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jpauclair.wordpress.com/674/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jpauclair.wordpress.com/674/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jpauclair.wordpress.com/674/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jpauclair.wordpress.com/674/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jpauclair.wordpress.com/674/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jpauclair.wordpress.com/674/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jpauclair.wordpress.com/674/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jpauclair.wordpress.com/674/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jpauclair.wordpress.com/674/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jpauclair.wordpress.com/674/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jpauclair.wordpress.com/674/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jpauclair.wordpress.com/674/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=674&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jpauclair.net/2011/09/27/flash11-session-sneak-peak/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/ff60a0adbbe0ae671125435044931eb1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jpauclair</media:title>
		</media:content>
	</item>
		<item>
		<title>Massive 3D Particle System in Flash Molehill</title>
		<link>http://jpauclair.net/2011/07/18/massive-3d-particle-system-in-flash-molehill/</link>
		<comments>http://jpauclair.net/2011/07/18/massive-3d-particle-system-in-flash-molehill/#comments</comments>
		<pubDate>Tue, 19 Jul 2011 01:42:26 +0000</pubDate>
		<dc:creator>jpauclair</dc:creator>
				<category><![CDATA[general]]></category>

		<guid isPermaLink="false">http://jpauclair.net/?p=639</guid>
		<description><![CDATA[Evolution of Molehill I&#8217;ve been working on Molehill for more than a year now. Since the very first iteration, to what we have now&#8230; wow there was a huge evolution. Evolution (countless changes) in the API and features Evolution in performances And a lot of evolution in the community. I have never seen such a [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=639&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h3>Evolution of Molehill</h3>
<p>I&#8217;ve been working on Molehill for more than a year now.</p>
<p>Since the very first iteration, to what we have now&#8230; wow there was a huge evolution.</p>
<ul>
<li>Evolution (countless changes) in the API and features</li>
<li>Evolution in performances</li>
<li>And a lot of evolution in the community.</li>
</ul>
<div>I have never seen such a great group of people working at the same time on a pre-release, in all possible application of the tech.</div>
<div>Still! When I look at the demos out there today, there is not much!</div>
<div>You can take a look at &#8220;<a title="The Big List of Molehill Demos " href="http://www.leebrimelow.com/?p=2607">The big list</a>&#8221; by Lee Brimelow</div>
<h3>An old thread</h3>
<p>can you remember the debate about PixelBender vs pure AS3 vs haxe?<br />
Let me help you remember! There was a nice attempt by a lot of people on the net to do a massive particle system with flash.<br />
A lot of comparison have been done between different way by the &#8220;masters&#8221;, and to honor theses efforts, I tought I&#8217;de make something with Molehill out of this old thread.</p>
<p>PixelBender+Alchemy option (by Ralph Hauwert)<br />
<a title="http://www.unitzeroone.com/blog/2009/03/18/flash-10-massive-amounts-of-3d-particles-with-alchemy-source-included/" href="http://www.unitzeroone.com/blog/2009/03/18/flash-10-massive-amounts-of-3d-particles-with-alchemy-source-included/">http://www.unitzeroone.com/blog/2009/03/18/flash-10-massive-amounts-of-3d-particles-with-alchemy-source-included/</a><br />
Pure AS3 option (by Joa Ebert)<br />
<a title="http://blog.joa-ebert.com/2009/04/03/massive-amounts-of-3d-particles-without-alchemy-and-pixelbender/" href="http://blog.joa-ebert.com/2009/04/03/massive-amounts-of-3d-particles-without-alchemy-and-pixelbender/">http://blog.joa-ebert.com/2009/04/03/massive-amounts-of-3d-particles-without-alchemy-and-pixelbender/</a></p>
<p>haXe:<br />
<a title="http://webr3.org/blog/haxe/flash-10-massive-amounts-of-3d-particles-with-haxe/" href="http://webr3.org/blog/haxe/flash-10-massive-amounts-of-3d-particles-with-haxe/">http://webr3.org/blog/haxe/flash-10-massive-amounts-of-3d-particles-with-haxe/</a></pre>
<p>&nbsp;</p>
<h3>Revamping an old post</h3>
<p>It's always fun to play with particle system when using a new tech.</p>
<p>Today I'm presenting to you one of the very first proof of concept I made with molehill, using a technique we developed at <a title="Frima Studio" href="http://frimastudio.com/">Frima Studio</a>. (Already one year ago!)</p>
<p>So I went in my archive and fixed all the API changes that were made since then.</p>
<p>There was also an old blog post going with it that I never released due to the "to early stage" of molehill pre-release, and the technological advantage of open-sourcing such as technique.</p>
<p>But since then there was a lot of development... First the presentation at <strong>Adobe Max 2010</strong> of the <a title="ZombieTycoon Trailer" href="http://www.youtube.com/watch?v=szaXvTsoeVs" target="_blank"> ZombieTycoon trailer</a>, Then The featured release of a couple of<a title="ZombieTycoon Demo" href="molehill.zombietycoon.com" target="_blank"> Zombie Tycoon levels</a>, the  session at <strong>Flash Gaming Summit 2011</strong> and the session for the<a href="http://www.sanflashcisco.com/" target="_blank"> San Flashisco</a> user group. And internally at frima, the tech never stopped to grow!</p>
<p>We are going to present at <strong>Adobe Max 2011</strong>.  I'm sure it's going to be awesome this year (again!).</p>
<h3>The Particle System</h3>
<p>This is a very simple particle system.<br />
The particle position are defined using a classic "Strange attractor" algorithm.<br />
Each particle is made with a quad and  is facing the camera (Billboard)</p>
<p><span class="Apple-style-span" style="font-size:15px;font-weight:bold;">Batching</span></p>
<p>THE most important thing when doing a particle system is to have a good batching process.<br />
Particles are often in very high numbers, and they must be drawable in batch to keep the performances high enough.</p>
<p>When we first started thinking about it, it was pretty obvious that to create something nice with billboards, we would have to transform each quad to make it face the screen (Transform by the Inverse ViewProjMatrix).  While this might sound obvious and simple to do, when processing the vertex in a vertex shader that process them one by one with no index or whatsoever defining what corners we are processing, it's not "that" obvious!</p>
<h4>The problem</h4>
<p>The transformation needed on the four corners of your quad is not the same! but you can only define "one way" of doing things in your shader. (No if statement). Hence, if you can't differentiate what you are processing, how can you make the good transformation to each vertex??</p>
<p>After a couple iteration where the CPU was doing the matrix transformation and re-uploaded each position each frame... We went in another direction. (It was WAY to heavy!)</p>
<p>The vertex shader let you define constant that you can access within the shader. Sadly, you have only 128 Float4 of theses.<br />
So no real way of "batching" large amount of particles by making a list of transformation for each vertex. The best you could do is a couple of dynamic particle at the same time.</p>
<h4>The trick</h4>
<p><span id="more-639"></span></p>
<p>The thing you can do is mix between your vertex arguments (position, scale, uv, etc. defined for each single vertex ) and the Vertex shader constants (limited).<br />
In your vertex arguments, you can define an ID for each corner of a quad: 1,2,3,4.<br />
Then, assign the exact same 3D position (center of the quad) to all 4 vertex.<br />
By setting only one position (4 time the same position) it means that it require the exact same transformation for all corners of your quad. (yeah!) But then, you have to be able to "re-construct" your quad inside the shader</p>
<p>In the Constants, you define an offset.xy from the center to each of the corners.<br />
And then, when processing the vertex in the shader, it can read the ID of the current vertex, which can then be use to access the offset matching the current vertex in the constants.</p>
<p>You can now recover your quad by offsetting the center of each vertex (Yeah #2!)</p>
<p>So the final algorithm is:</p>
<p><pre class="brush: as3;">

//VertexShader

position = argument[0].xyz // Center of the quad
id = argument[0].w //ID=1 | 2 | 3 | 4
Offset = Constants[id]
transform the Offset of the current corner by the Inverse ViewProj Matrix //billboard
Add the result to the vertex position
transform finalPosition by the ViewProj Matrix  //Show on screen

</pre></p>
<h3>SpriteSheet Manipulation</h3>
<p>The technique used here is to modify the UV of each particles in a bytearray, and send it back to the Video Card.</p>
<p><pre class="brush: as3;">
for each(particle in particleList)
	Set Vertex1.uv = particle.nextframe()
	Set Vertex2.uv = particle.nextframe()
	Set Vertex3.uv = particle.nextframe()
	Set Vertex4.uv = particle.nextframe()
UpdateVertexBuffer(ParticleList)
</pre></p>
<p>The same result could be achieved using a full GPU particle system. with the UV changing over time using an offset in function of time.</p>
<p>But to represent a system where each particle would move independently with physics for example, it was best to re-upload the whole thing.</p>
<p>the texture is a space-core SpriteSheet (sphere with rotating rings around)</p>
<p>The format original was a PNG with transparency<br />
I decided to split that up in two, and compress them with the ATF file format.</p>
<p><img title="SpaceCore Diffuse" src="http://flashpatrol.net/jpauclair.net/MassiveAmoutOfParticles/space-core_black.png" alt="SpaceCore Diffuse" width="512" height="160" /></p>
<p>As you can see, the background is black.<br />
To be able to use transparency, I made a alpha mask for it:<br />
<img title="SpaceCore Mask" src="http://flashpatrol.net/jpauclair.net/MassiveAmoutOfParticles/space-core_mask.png" alt="SpaceCore Mask" width="512" height="160" /></p>
<p>I could have used the original png, and kill transparent pixels.<br />
But to do that I need a texture with 4 channels (RGBA). Which means that I cannot use ATF texture compression.<br />
After benchmarking it, doing a sampling in two ATF is faster than doing only one in a uncompressed bitmap.<br />
Hence I went with the compression (and of course, not only it's faster, but smaller in video memory)<br />
One of the goal of this demo was to determine what was the balance between process on the CPU and GPU.</p>
<h3>Final result</h3>
<p>Don't forget to use the latest <a title="Flash Player 11 Incubator build" href="http://labs.adobe.com/technologies/flashplatformruntimes/incubator/" target="_blank">Flash Player 11 Incubator build</a><br />
<a href="http://flashpatrol.net/jpauclair.net/MassiveAmoutOfParticles/index.html"><img class="alignnone" title="Particle System" src="http://flashpatrol.net/jpauclair.net/MassiveAmoutOfParticles/ParticleSystem.png" alt="Particle System" width="460" height="361" /></a></p>
<h3></h3>
<p>If you think of better/other ways to do the same thing, please comments in here! Sharing is good <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>Sources</h3>
<p>I know you guys are hungry for some code!</p>
<p><a title="Massive Amount Of particles Demo" href="https://jpauclair-blog.googlecode.com/svn/trunk/Experiment/MassiveAmountOfParticleDemo/Main_UV_CPU.as" target="_blank">The whole thing is here</a></p>
<h3>frima</h3>
<p><a href="www.frimastudio.com"><img class="alignleft" title="logo frima" src="http://flashpatrol.net/jpauclair.net/MassiveAmoutOfParticles/logo_frima.png" alt="" width="41" height="60" /></a> As I was saying. This demo is now one year old and frima as pushed the limits of Molehill non-stop since it was first pre-released.</p>
<p>Just imagine what we are able to do right now, and how this is going to change the face of the gaming industry!</p>
<h3>Teaser</h3>
<p>Yup! I am about to release a new version of <a href="http://jpauclair.net/FlashPreloadProfiler" target="_blank">FlashPreloadProfiler</a>. It's now very complete and I will be proud to release it in a couple of days! I hope you will stay tuned!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jpauclair.wordpress.com/639/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jpauclair.wordpress.com/639/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jpauclair.wordpress.com/639/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jpauclair.wordpress.com/639/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jpauclair.wordpress.com/639/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jpauclair.wordpress.com/639/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jpauclair.wordpress.com/639/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jpauclair.wordpress.com/639/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jpauclair.wordpress.com/639/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jpauclair.wordpress.com/639/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jpauclair.wordpress.com/639/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jpauclair.wordpress.com/639/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jpauclair.wordpress.com/639/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jpauclair.wordpress.com/639/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=639&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jpauclair.net/2011/07/18/massive-3d-particle-system-in-flash-molehill/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/ff60a0adbbe0ae671125435044931eb1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jpauclair</media:title>
		</media:content>

		<media:content url="http://flashpatrol.net/jpauclair.net/MassiveAmoutOfParticles/space-core_black.png" medium="image">
			<media:title type="html">SpaceCore Diffuse</media:title>
		</media:content>

		<media:content url="http://flashpatrol.net/jpauclair.net/MassiveAmoutOfParticles/space-core_mask.png" medium="image">
			<media:title type="html">SpaceCore Mask</media:title>
		</media:content>

		<media:content url="http://flashpatrol.net/jpauclair.net/MassiveAmoutOfParticles/ParticleSystem.png" medium="image">
			<media:title type="html">Particle System</media:title>
		</media:content>

		<media:content url="http://flashpatrol.net/jpauclair.net/MassiveAmoutOfParticles/logo_frima.png" medium="image">
			<media:title type="html">logo frima</media:title>
		</media:content>
	</item>
		<item>
		<title>ZombieTycoon &amp; Molehill Session at FlashGamingSummit</title>
		<link>http://jpauclair.net/2011/03/01/zombietycoon-molehill-session-at-flashgamingsummit/</link>
		<comments>http://jpauclair.net/2011/03/01/zombietycoon-molehill-session-at-flashgamingsummit/#comments</comments>
		<pubDate>Tue, 01 Mar 2011 09:50:01 +0000</pubDate>
		<dc:creator>jpauclair</dc:creator>
				<category><![CDATA[general]]></category>

		<guid isPermaLink="false">http://jpauclair.net/?p=624</guid>
		<description><![CDATA[I, Speaker This weekend I was a speaker in a conference for the very first time. And then, monday at this one I must say, it was damn exiting. Event more when it&#8217;s to talk about the very first game using the a technology that people has waited for years. Adobe has even used our [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=624&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h2>I, Speaker</h2>
<p>This weekend I was a speaker in a <a href="http://www.flashgamingsummit.com/">conference</a> for the very first time.</p>
<p>And then, monday at <a href="http://flashongames.eventbrite.com/">this one</a></p>
<p>I must say, it was damn exiting. Event more when it&#8217;s to talk about the very first game using the a <a href="http://labs.adobe.com/technologies/flashplatformruntimes/incubator/">technology that people has waited for years</a>.</p>
<p>Adobe has even used our project as the <a href="http://labs.adobe.com/technologies/flashplatformruntimes/incubator/features/molehill.html">featured  game using Molehill</a> for it&#8217;s official beta release.</p>
<p>The session was shared between Luc beaulieu (CTO) and me, both representing <a href="http://frimastudio.com/">Frima Studio</a>.</p>
<p>My session was about many techniques we used to create <a href="http://molehill.zombietycoon.com/">ZombieTyccon</a> and how we managed to work with the limitations defined in Molehill.</p>
<p>I though it could be great to share this to everyone.</p>
<h2>The session</h2>
<p><a title="ZombieTycoon slides for the FlashGamingSummit" href="http://molehill.zombietycoon.com/FGSZombieNoVideos.pptx">download the Slides</a> (powerpoint)</p>
<h2>The videos</h2>
<p><span id="more-624"></span><br />
There was many videos in the slides, so now they are all on YouTube.</p>
<p>Here is a little demo of hundreds of zombies walking around in the level 3. (If you wonder why they are so strong, well&#8230; I wanted them to stay alive until the end of the level! )</p>
<p><a href="http://www.youtube.com/watch?v=hHXfUMe2AnE"><span style="text-align:center; display: block;"><a href="http://jpauclair.net/2011/03/01/zombietycoon-molehill-session-at-flashgamingsummit/"><img src="http://img.youtube.com/vi/McvUCP0ijVE/2.jpg" alt="" /></a></span></a></p>
<p>&nbsp;</p>
<p>But here is the real way to kill zombies. First, get guns, then, kill em!</p>
<p><a href="http://www.youtube.com/watch?v=hHXfUMe2AnE"><span style="text-align:center; display: block;"><a href="http://jpauclair.net/2011/03/01/zombietycoon-molehill-session-at-flashgamingsummit/"><img src="http://img.youtube.com/vi/OBPzWupv2hc/2.jpg" alt="" /></a></span></a></p>
<p>&nbsp;</p>
<p>And again the level 3</p>
<p><a href="http://www.youtube.com/watch?v=hHXfUMe2AnE"><span style="text-align:center; display: block;"><a href="http://jpauclair.net/2011/03/01/zombietycoon-molehill-session-at-flashgamingsummit/"><img src="http://img.youtube.com/vi/WAcO6KcMAfA/2.jpg" alt="" /></a></span></a></p>
<p>&nbsp;</p>
<p>Here is the particle system. You can see smoke, shells, fire, even the health bars are particles.</p>
<p><a href="http://www.youtube.com/watch?v=hHXfUMe2AnE"><span style="text-align:center; display: block;"><a href="http://jpauclair.net/2011/03/01/zombietycoon-molehill-session-at-flashgamingsummit/"><img src="http://img.youtube.com/vi/_vYHVS5VzWs/2.jpg" alt="" /></a></span></a></p>
<p>&nbsp;</p>
<p>In my slides I&#8217;m talking about the possibility of rendering 16K particles per draw call. This is what it looks like.</p>
<p><a href="http://www.youtube.com/watch?v=hHXfUMe2AnE"><span style="text-align:center; display: block;"><a href="http://jpauclair.net/2011/03/01/zombietycoon-molehill-session-at-flashgamingsummit/"><img src="http://img.youtube.com/vi/CsSfZ42iX8c/2.jpg" alt="" /></a></span></a></p>
<p>&nbsp;</p>
<p>Thats is our character animation system. It use the DualQuaternion technique, with animation blending (transition). In this demo, notice the characters are changing animation multiple time and it&#8217;s always very smooth.</p>
<p><a href="http://www.youtube.com/watch?v=hHXfUMe2AnE"><span style="text-align:center; display: block;"><a href="http://jpauclair.net/2011/03/01/zombietycoon-molehill-session-at-flashgamingsummit/"><img src="http://img.youtube.com/vi/y_HSPkA4fPk/2.jpg" alt="" /></a></span></a></p>
<p>&nbsp;</p>
<p>We also support dynamic lighting to help creating great ambiance.</p>
<p>You can see the influence of the light on the fence, the ground, the avatars,  all objects near the barrels. You can also see that this dynamic light is using a very smooth falloff.</p>
<p><a href="http://www.youtube.com/watch?v=hHXfUMe2AnE"><span style="text-align:center; display: block;"><a href="http://jpauclair.net/2011/03/01/zombietycoon-molehill-session-at-flashgamingsummit/"><img src="http://img.youtube.com/vi/BVCz1i2BrTE/2.jpg" alt="" /></a></span></a></p>
<p>&nbsp;</p>
<p>In this video, the machine gun is blinking a dynamic light at every gun shot. You can see the influence on the avatars, the ground and many other objects.</p>
<p><a href="http://www.youtube.com/watch?v=hHXfUMe2AnE"><span style="text-align:center; display: block;"><a href="http://jpauclair.net/2011/03/01/zombietycoon-molehill-session-at-flashgamingsummit/"><img src="http://img.youtube.com/vi/rWLxZBp3nBo/2.jpg" alt="" /></a></span></a></p>
<p>&nbsp;</p>
<p>While using dynamic lighting is heavy on the GPU, using fake volumetric lighting is a lot more lightweight. To create this, we set a couple particles under the streetlights and the police&#8217;s cars lights</p>
<p><a href="http://www.youtube.com/watch?v=hHXfUMe2AnE"><span style="text-align:center; display: block;"><a href="http://jpauclair.net/2011/03/01/zombietycoon-molehill-session-at-flashgamingsummit/"><img src="http://img.youtube.com/vi/C4ABbV7JW8A/2.jpg" alt="" /></a></span></a></p>
<p>&nbsp;</p>
<p>Again, in order to make the game run faster, we used fake projected shadows. Using particle aligned to the ground, we cast shadow behind dynamic object depending on light position and intensity, we stretch the particle to fit.</p>
<p><a href="http://www.youtube.com/watch?v=hHXfUMe2AnE"><span style="text-align:center; display: block;"><a href="http://jpauclair.net/2011/03/01/zombietycoon-molehill-session-at-flashgamingsummit/"><img src="http://img.youtube.com/vi/YQPd_srwJKw/2.jpg" alt="" /></a></span></a></p>
<p>&nbsp;</p>
<p>Finaly, this is the the gameplay of the first level (tutorial)</p>
<p><a href="http://www.youtube.com/watch?v=hHXfUMe2AnE"><span style="text-align:center; display: block;"><a href="http://jpauclair.net/2011/03/01/zombietycoon-molehill-session-at-flashgamingsummit/"><img src="http://img.youtube.com/vi/IOFcPh0NFNc/2.jpg" alt="" /></a></span></a></p>
<p>&nbsp;</p>
<h2>Play the game</h2>
<p><a href="http://molehill.zombietycoon.com/">http://molehill.zombietycoon.com/</a></p>
<p>&nbsp;</p>
<p>Give me feedbacks!</p>
<p>The two session were recorded and I will post the video as soon as they become availables!</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jpauclair.wordpress.com/624/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jpauclair.wordpress.com/624/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jpauclair.wordpress.com/624/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jpauclair.wordpress.com/624/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jpauclair.wordpress.com/624/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jpauclair.wordpress.com/624/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jpauclair.wordpress.com/624/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jpauclair.wordpress.com/624/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jpauclair.wordpress.com/624/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jpauclair.wordpress.com/624/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jpauclair.wordpress.com/624/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jpauclair.wordpress.com/624/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jpauclair.wordpress.com/624/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jpauclair.wordpress.com/624/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=624&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jpauclair.net/2011/03/01/zombietycoon-molehill-session-at-flashgamingsummit/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/ff60a0adbbe0ae671125435044931eb1?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jpauclair</media:title>
		</media:content>
	</item>
	</channel>
</rss>
