<?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>Mon, 20 May 2013 13:12:59 +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>&#8220;Adobe Gaming Summit&#8221; Post-mortem</title>
		<link>http://jpauclair.net/2012/08/07/adobe-gaming-summit-post-mortem/</link>
		<comments>http://jpauclair.net/2012/08/07/adobe-gaming-summit-post-mortem/#comments</comments>
		<pubDate>Tue, 07 Aug 2012 13:00:21 +0000</pubDate>
		<dc:creator>jpauclair</dc:creator>
				<category><![CDATA[actionscript]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[Adobe]]></category>
		<category><![CDATA[flash is dead]]></category>

		<guid isPermaLink="false">http://jpauclair.net/?p=867</guid>
		<description><![CDATA[I was a speaker at this summit both as the owner of TheMiner, and a R&#38;D Architect at Frima studio, and I wanted to talk to you a bit about what was the event, and what (as a developer) I learned there. But first, you should read the blog post by Thibault to get details about what &#8230; &#8230; <a href="http://jpauclair.net/2012/08/07/adobe-gaming-summit-post-mortem/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=867&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I was a speaker at this summit both as the owner of <a title="TheMiner" href="http://www.sociodox.com/theminer/">TheMiner</a>, and a R&amp;D Architect at <a title="Frima Studio" href="http://www.frimastudio.com">Frima studio</a>, and I wanted to talk to you a bit about what was the event, and what (as a developer) I learned there.</p>
<p>But first, you should read the blog post by Thibault to get details about what Adobe learned from the summit (<a title="Adobe Gaming Summit" href="http://www.bytearray.org/?p=4746">Read This</a>)</p>
<p>This summit was a really good mix between<br />
Speaker: Giving their short/mid/long term feature requests, giving bug report and commenting on better pipe-line  solutions<br />
Adobe: Reveling and explaining lot&#8217;s of &#8220;What&#8217;s next&#8221; in the form of a mini &#8220;Adobe Max Sneak Peaks&#8221;</p>
<p>Did you ever attend an <a title="Max" href="http://max.adobe.com/">Adobe Max Conference</a> Sneak peaks? Pretty cool.</p>
<p>So let&#8217;s just follow Thibault post structure:<br />
And I know it&#8217;s going to be so disappointing for all you guys&#8230;. but here it is!</p>
<p><strong>1. The workflow</strong></p>
<ul>
<li>What if you could gain time&#8230; lot&#8217;s of it..</li>
<li>What if you could integrate in better ways to your &#8220;full pipe-line&#8221;&#8230;</li>
<li>What if you artist could stop complaining? (lol)</li>
</ul>
<p><strong>2. Performance</strong></p>
<ul>
<li>What if your compile time would reduce a lot&#8230;</li>
<li>I&#8217;m sure you know how many blogs talk about little as3 optimization to make code run faster.
<ul>
<li>What if they would become&#8230; all&#8230; obsolete&#8230;</li>
<li>What if the only performance boost you will get could be from better algorithm?</li>
<li>What if you could completely trust who&#8217;s making the update?</li>
</ul>
</li>
</ul>
<p><strong>3. Perception</strong></p>
<ul>
<li>What if you could really think &#8220;Flash is far from dead&#8221;</li>
<li>What if would you&#8217;d expect to present to 3 Adobe senior engineer, and you would get 100 engineers in an auditorium, and a whole lot more online in an internal event streaming to all the Adobe employees that can make what&#8217;s coming next.</li>
<li>What if my own skepticism was yelling: &#8220;Fuck, they are really serious about this&#8230;&#8221;</li>
</ul>
<p><strong>4. Project &#8220;Monocle&#8221; </strong>(As the owner of TheMiner)</p>
<ul>
<li>What if the tools they are making could compete to what&#8217;s best of other technology?</li>
<li>What if you could &#8220;trust&#8221; the data that is being outputted?</li>
<li>What if the next version of the VM would be built with a lot of telemetry from the scratch?</li>
</ul>
<p>&nbsp;</p>
<p><strong>5. Post-Mortem</strong></p>
<p>I guess the most important thing here is commitment.</p>
<p>I worked on flash project and R&amp;D for a very long time now. And all the sudden, they just want to raise that bar to a level you would not expect.</p>
<p>This is a very exiting time for me as, suddenly, I feel like I&#8217;m being a key role in what &#8220;has been&#8221; flash gaming in the past, and certainly in what&#8217;s &#8220;will be&#8221; flash in the future.</p>
<p>I won&#8217;t talk about other technology here, but I am now 100% confident that this blog is not soon to be dead.</p>
<p>And if clients come-up and ask &#8220;what technology should we use&#8221;,  I&#8217;ll be more than ever happy to answer.</p>
<p>&nbsp;</p>
<p><strong>5. Frima Icefield 3D &#8211; World Editor Trailer</strong></p>
<p>This is a video made from a couple thing we showed there. (it&#8217;s available in 720p)<br />
*please, do not blink your eyes, and crank-up your speaker!*</p>
<p>&nbsp;<br />
<a href="http://www.youtube.com/watch?v=WV1JqbhiE1Y"><span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='584' height='359' src='http://www.youtube.com/embed/WV1JqbhiE1Y?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0'></iframe></span></a><br />
&nbsp;</p>
<p>Thanks for reading, and I hope this all make you really happy.</p>
<p>I just want to give a special thanks to Thibault and the other Adobe folks who made this all possible.</p>
<p>&nbsp;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jpauclair.wordpress.com/867/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jpauclair.wordpress.com/867/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=867&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jpauclair.net/2012/08/07/adobe-gaming-summit-post-mortem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.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>New tutorial: Profiling memory with TheMiner</title>
		<link>http://jpauclair.net/2012/07/11/new-tutorial-profiling-memory-with-theminer/</link>
		<comments>http://jpauclair.net/2012/07/11/new-tutorial-profiling-memory-with-theminer/#comments</comments>
		<pubDate>Thu, 12 Jul 2012 02:47:10 +0000</pubDate>
		<dc:creator>jpauclair</dc:creator>
				<category><![CDATA[actionscript]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[optimization]]></category>

		<guid isPermaLink="false">http://jpauclair.net/?p=861</guid>
		<description><![CDATA[Tutorial: Using the Memory profiler Most of the time, Flash performance issues come from bad memory management. Object instantiation take a lot of time, and since FlashPlayer work with a Garbage Collector, having tons of objects can make it go nuts. Good practice is to remove all instantiation from loops, keep a minimum of object &#8230; &#8230; <a href="http://jpauclair.net/2012/07/11/new-tutorial-profiling-memory-with-theminer/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=861&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<h2><strong>Tutorial: Using the Memory profiler</strong></h2>
<p>Most of the time, Flash performance issues come from bad memory management.<br />
Object instantiation take a lot of time, and since FlashPlayer work with a Garbage Collector, having tons of objects can make it go nuts.<br />
Good practice is to remove all instantiation from loops, keep a minimum of object in memory and use serialization and bytearrays to keep some data.</p>
<p>This profiler show you what the VM is reporting as object being allocated and removed (garbage collected).<br />
Here is what the profiler look like:</p>
<p><a href="http://www.sociodox.com/theminer/tutorial/tutorial_feature_memory_profiler.html"><img class="aligncenter" title="TheMiner Memory Profiler" src="http://www.sociodox.com/theminer/tutorial/images/MemoryProfiler_features.png" alt="" width="640" height="358" /></a><br />
<span style="font-size:large;">1.</span> <strong>Search filter</strong></p>
<p>Since there is a lot of different object type being managed by the VM,<br />
just listing them would make it hard to find specific data.<br />
This input box let you enter any text to filter the visible object using their QName</p>
<p>When the filter search is ON (there is text inside the box), the box appear green,<br />
and only class name with the text in it appear in the list.</p>
<p><a href="http://www.sociodox.com/theminer/tutorial/tutorial_feature_memory_profiler.html"><img class="aligncenter" title="Memory Profiler Sear Filter" src="http://www.sociodox.com/theminer/tutorial/images/MemoryProfiler_Search.png" alt="" width="640" height="358" /></a><br />
<span style="font-size:large;">2.</span> <strong>Class QName</strong></p>
<p>The QName is the ClassName with its full ClassPath. the format is ClassPath::ClassName<br />
<span style="font-size:large;">3.</span> <strong>Avg new / frame</strong></p>
<p>When profiling memory, high number of instantiation might be harder to understand.<br />
Having an average instantiation per frame let the developer understand the exact amount of allocation in a single frame</p>
<p><a href="http://www.sociodox.com/theminer/tutorial/tutorial_feature_memory_profiler.html"><img class="aligncenter" title="MemoryProfiler AvgPerFrame" src="http://www.sociodox.com/theminer/tutorial/images/MemoryProfiler_AvgPerFrame.png" alt="" width="640" height="358" /></a><br />
<span style="font-size:large;">4.</span> <strong>Sample snapshot</strong></p>
<p>The miner cannot guess all the post-analysis you want to do.<br />
But it does offer you a easy way to save data in a grid format that can be pasted directly in excel<br />
If you need to save the current state, or do graphics using the data in the profiler,<br />
you can use the snapshot button to copy all class to the clipboard with all their numbers.</p>
<p><a href="http://www.sociodox.com/theminer/tutorial/tutorial_feature_memory_profiler.html"><img class="aligncenter" title="MemoryProfiler Snapshot" src="http://www.sociodox.com/theminer/tutorial/images/MemoryProfiler_Snapshot.png" alt="" width="640" height="358" /></a><br />
<span style="font-size:large;">5.</span> <strong>Clear all samples</strong></p>
<p>Reset the current instance count and cumulative instance count for all class.</p>
<p><span style="font-size:large;">6.</span> <strong>Pause refresh</strong></p>
<p>Toggle button that keep retrieving sampling data, but stop the interface refresh.</p>
<p><span style="font-size:large;">7.</span> <strong>Added per second(default refresh-rate)</strong></p>
<p>Number of Class instantiated in one second The default refresh rate can be change in the configuration tab</p>
<p><span style="font-size:large;">8.</span> <strong>Deleted per second(default refresh-rate)</strong></p>
<p>Number of Class being collected by the GC in one second The default refresh rate can be change in the configuration tab</p>
<p><span style="font-size:large;">9.</span> <strong>Sort by Current Instance Count</strong></p>
<p>Sort by Current Instance Count</p>
<p><span style="font-size:large;">10.</span> <strong>Current Instance Count</strong></p>
<p>The current instance count is calculated by removing Collected Sample to New Sample.<br />
This number is significant only when the memory profiler continuous profiling is turned-on in the configuration tab<br />
because all sample report must be processed in order to have a good count.</p>
<p><span style="font-size:large;">11.</span> <strong>Sort by Cummulative Instance Count</strong></p>
<p>Sort by Cummulative Instance Count</p>
<p><span style="font-size:large;">12.</span> <strong>Cummulative Instance Count</strong></p>
<p>The total number of Instanciation for a given class type.</p>
<p>&nbsp;</p>
<h2>Try TheMiner!</h2>
<p><a href="http://www.sociodox.com/theminer/"><img class="alignleft" title="TheMiner" src="http://www.sociodox.com/theminer/images/the_miner_banner.png" alt="" width="238" height="60" /></a></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/861/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jpauclair.wordpress.com/861/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=861&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jpauclair.net/2012/07/11/new-tutorial-profiling-memory-with-theminer/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.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://www.sociodox.com/theminer/tutorial/images/MemoryProfiler_features.png" medium="image">
			<media:title type="html">TheMiner Memory Profiler</media:title>
		</media:content>

		<media:content url="http://www.sociodox.com/theminer/tutorial/images/MemoryProfiler_Search.png" medium="image">
			<media:title type="html">Memory Profiler Sear Filter</media:title>
		</media:content>

		<media:content url="http://www.sociodox.com/theminer/tutorial/images/MemoryProfiler_AvgPerFrame.png" medium="image">
			<media:title type="html">MemoryProfiler AvgPerFrame</media:title>
		</media:content>

		<media:content url="http://www.sociodox.com/theminer/tutorial/images/MemoryProfiler_Snapshot.png" medium="image">
			<media:title type="html">MemoryProfiler Snapshot</media:title>
		</media:content>

		<media:content url="http://www.sociodox.com/theminer/images/the_miner_banner.png" medium="image">
			<media:title type="html">TheMiner</media:title>
		</media:content>
	</item>
		<item>
		<title>A few big additions : 1.4.00</title>
		<link>http://jpauclair.net/2012/07/02/a-few-big-additions-1-4-00/</link>
		<comments>http://jpauclair.net/2012/07/02/a-few-big-additions-1-4-00/#comments</comments>
		<pubDate>Mon, 02 Jul 2012 22:56:23 +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>

		<guid isPermaLink="false">http://jpauclair.net/?p=850</guid>
		<description><![CDATA[Released:  TheMiner 1.4.00 I&#8217;ll skip the usual &#8220;we fixed bugs&#8221; part, and go straight to what&#8217;s new and interesting! Here is a quick overview of the biggest additions: UserEvents A UserEvent is a event created by the developer in the application that will communicate with TheMiner to show up in a specific tab of TheMiner &#8230; &#8230; <a href="http://jpauclair.net/2012/07/02/a-few-big-additions-1-4-00/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=850&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<h2><a href="http://www.sociodox.com/theminer"><img class="alignleft" title="TheMiner" src="http://www.sociodox.com/theminer/images/the_miner_banner.png" alt="" width="238" height="60" /></a></h2>
<h2></h2>
<h2></h2>
<h2></h2>
<h2>Released:  TheMiner 1.4.00</h2>
<p>I&#8217;ll skip the usual &#8220;we fixed bugs&#8221; part, and go straight to what&#8217;s new and interesting!</p>
<p>Here is a quick overview of the biggest additions:</p>
<h3>UserEvents</h3>
<p>A UserEvent is a event created by the developer in the application that will communicate with TheMiner to show up in a specific tab of TheMiner (UserEvent tab).<br />
The event can be pushed to TheMiner in two ways:</p>
<ul>
<li><strong>TheMiner.AddBasicUserEvent</strong>(aEventName:String = null, aEventValue1:* = null): UserEventEntry</li>
<li><strong>TheMiner.AddCustomUserEvent</strong>(aEventName:String = null, aEventInfo:String = null, aEventValue1:* = null, aEventValue2:* = null, aStatusBarLabel:String = null, aStatusBarProgress:Number = -1, aStatusBarColor:uint = 0xFF000000, aEventSortPriority:int = 0, aEventVisible:Boolean = true, aError:Boolean = false): UserEventEntry</li>
</ul>
<p>This is  what it can look like:</p>
<p><a href="http://www.sociodox.com/theminer/feature.html#UserEvents"><img class="aligncenter" title="UserEvents_updatable" src="http://www.sociodox.com/theminer/tutorial/images/user_events_updatable_2.png" alt="" width="550" height="194" /></a></p>
<h3></h3>
<h3></h3>
<h3>static/dynamic Logging platform</h3>
<p>Logging is pretty straight forward? wrong. This can easily become a mess.</p>
<p>In this new version,you can use a sub-set of FlashConsole, well integrated with TheMiner.</p>
<p>using simple command such as</p>
<pre class="brush: as3; title: ; notranslate">
//Simple log
TheMiner.Log(&quot;My Simple Log&quot;);

//Log to a specific channel
TheMiner.Log(&quot;Simple Channel Log&quot;,&quot;MyChannel&quot;);
</pre>
<div>But logging is not the only possibility.</div>
<div>This tool also let you inspect object and classes.</div>
<pre class="brush: as3; title: ; notranslate">
//Inspecting(dynamic log) a Class definition
TheMiner.Log(&quot;Inspecting a class&quot;,&quot;Inspect&quot;);
TheMiner.InspectObject(MyClassToInspect, &quot;Inspect&quot;);

//Inspecting(dynamic log) a Object Instance
TheMiner.Log(&quot;-------------------------------------------&quot;);
TheMiner.Log(&quot;Inspecting an instance&quot;,&quot;Inspect&quot;);
mObjToInspect = new MyClassToInspect();
TheMiner.InspectObject(mObjToInspect, &quot;Inspect&quot;);

//Class to print out
class MyClassToInspect

public var FirstVar:int = 0;
public var SecondVar:String = &quot;foo&quot;
}
</pre>
<div><a href="http://www.sociodox.com/theminer/feature.html#FlashConsole"><img class="aligncenter" title="FlashConsole_TheMiner" src="http://www.sociodox.com/theminer/tutorial/images/flash_console.png" alt="" width="550" height="550" /></a></div>
<h3></h3>
<h3></h3>
<h3>Better Filtered content</h3>
<p>You can now toggle a Permanent Search filters option in the configuration tab</p>
<p>By doing so, any text you enter in a given session inside one of the search box (MemoryProfiler, PerformanceProfiler, LoaderProfiler, UserEvents) will remain active after you close the application, and reloaded when you start a new session.</p>
<p>This way, when you do iterative work on optimizing your application, you don&#8217;t have to lo0se time on remembering, and re-entering the same info over and over again.</p>
<p>The Permanent Search Filters  are also used when using Raw Data Dumps, this way it&#8217;s a lot easier to track down precise information in those huuuge list of info.</p>
<h3></h3>
<h3>Average per frame</h3>
<p>Did you ever try to know precisely how much time you function are running?</p>
<p>The Performance profiler now offer a way to make a ratio of time taken by a function over a period, which give you a time that can be calculated in microseconds!</p>
<p><a href="http://www.sociodox.com/theminer/feature.html#FunctionProfiler"><img class="aligncenter" title="Performance_avg_per_frame" src="http://www.sociodox.com/theminer/tutorial/images/Performance_avg_per_frame.png" alt="" width="550" height="194" /></a></p>
<p>What do we have here&#8230;.</p>
<p>Each frame, around 23 microseconds is spent in the b2Mat22/Solve function calls</p>
<p>and 0.1 Millisecond in b2Mat22/Set</p>
<p>Do you have a Performance budget? This is the tool you need!</p>
<h3>Last but not least<strong>:</strong> The Resources Grabber</h3>
<p>Do you link directly to JPG and PNGs?</p>
<p>Do you load SWF at runtime? encrypted?</p>
<p>The resource grabber feature (in the Loader profiler) can expose, and redirect you directly to file being downloaded , and SWF being loaded by the VM.</p>
<p><a href="http://www.sociodox.com/theminer/feature.html#SWFSaver"><img class="aligncenter" title="swf_saver" src="http://www.sociodox.com/theminer/images/swfsaver.png" alt="" width="321" height="181" /></a></p>
<p>If it&#8217;s a simple media, clicking in a icon will pop-up a window and show you the file in your browser.</p>
<p>If it&#8217;s a SWF, it will ask you to save the SWF bytes in a file somewhere.</p>
<p>The file is the Unpacked, and Unencrypted version of any SWF.</p>
<p>This means you can pass it directly to a decompiler to check the content.</p>
<h3>TheMiner</h3>
<p>For those who already use TheMiner, you know that these are only little addition compare to what&#8217;s already in it.</p>
<p>I suggest you give it all a try to know if you like it! (you will)</p>
<p><a href="http://www.sociodox.com/theminer/"><img class="aligncenter" title="TheMiner" src="http://www.sociodox.com/theminer/images/the_miner_banner.png" alt="" width="238" height="60" /></a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jpauclair.wordpress.com/850/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jpauclair.wordpress.com/850/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jpauclair.net&#038;blog=10572069&#038;post=850&#038;subd=jpauclair&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jpauclair.net/2012/07/02/a-few-big-additions-1-4-00/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.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://www.sociodox.com/theminer/images/the_miner_banner.png" medium="image">
			<media:title type="html">TheMiner</media:title>
		</media:content>

		<media:content url="http://www.sociodox.com/theminer/tutorial/images/user_events_updatable_2.png" medium="image">
			<media:title type="html">UserEvents_updatable</media:title>
		</media:content>

		<media:content url="http://www.sociodox.com/theminer/tutorial/images/flash_console.png" medium="image">
			<media:title type="html">FlashConsole_TheMiner</media:title>
		</media:content>

		<media:content url="http://www.sociodox.com/theminer/tutorial/images/Performance_avg_per_frame.png" medium="image">
			<media:title type="html">Performance_avg_per_frame</media:title>
		</media:content>

		<media:content url="http://www.sociodox.com/theminer/images/swfsaver.png" medium="image">
			<media:title type="html">swf_saver</media:title>
		</media:content>

		<media:content url="http://www.sociodox.com/theminer/images/the_miner_banner.png" medium="image">
			<media:title type="html">TheMiner</media:title>
		</media:content>
	</item>
		<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 &#8230; &#8230; <a href="http://jpauclair.net/2012/03/12/fastsort-faster-is-better/">Continue reading <span class="meta-nav">&#8594;</span></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" />]]></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>
<pre class="brush: as3; title: ; notranslate">
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>
<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> <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://0.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 &#8230; &#8230; <a href="http://jpauclair.net/2012/02/25/epic-memory-track-down/">Continue reading <span class="meta-nav">&#8594;</span></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" />]]></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=584" 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>
<pre class="brush: as3; title: ; notranslate">
public class DO
{
	public var x:Number;
	public var y:Number;

	public function DO() { }
}
</pre>
<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>
<pre class="brush: as3; title: ; notranslate">
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>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>
<pre class="brush: as3; title: ; notranslate">
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>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=584" alt="" title="avm2Architecture"   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=584" alt="" title="CodeFlow"   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>
<pre class="brush: plain; title: ; notranslate">

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>And here is the output for the <strong>not</strong> strictly typed part:</p>
<pre class="brush: plain; title: ; notranslate">

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>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:</p>
<pre class="brush: plain; title: ; notranslate">
stack: DO?@86 Number@87
</pre>
<p>vs</p>
<pre class="brush: plain; title: ; notranslate">
stack: *@95 Number@96
</pre>
<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>
<pre class="brush: plain; title: ; notranslate">
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>
<p>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:</p>
<pre class="brush: plain; title: ; notranslate">
@99 cmop  AvmCore::intToAtom (@79, @98)
</pre>
<p>and on the other side you have:</p>
<pre class="brush: plain; title: ; notranslate">
@107 cmop  AvmCore::doubleToAtom_sse2 (@78, @106)
</pre>
<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>:</p>
<pre class="brush: cpp; title: ; notranslate">
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>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>
<pre class="brush: cpp; title: ; notranslate">
var j:int = 234;
</pre>
<p>I used</p>
<pre class="brush: cpp; title: ; notranslate">
var j:int = int.MAX_VALUE;
</pre>
<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>
<pre class="brush: cpp; title: ; notranslate">
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>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>
<pre class="brush: as3; title: ; notranslate">
var j:Number = 234.3948;
</pre>
<p>and used</p>
<pre class="brush: as3; title: ; notranslate">
var j:Number = 234;
</pre>
<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>
<pre class="brush: cpp; title: ; notranslate">
Atom allocDouble(double n)
{
	double *ptr = (double*)GetGC()-&amp;gt;Alloc(sizeof(double), 0);
	*ptr = n;
	return kDoubleType | (uintptr)ptr;
}
</pre>
<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>
<pre class="brush: as3; title: ; notranslate">
var anon:*;
for (var i:int = 0; i &amp;lt; 100000; i++) {
	anon = 3.3;
}
</pre>
<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=584" 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> <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>27</slash:comments>
	
		<media:content url="http://0.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 &#8230; &#8230; <a href="http://jpauclair.net/2012/01/12/updated-the-optimized-bas64-library/">Continue reading <span class="meta-nav">&#8594;</span></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" />]]></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>
<pre class="brush: as3; title: ; notranslate">

//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>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>
<pre class="brush: as3; title: ; notranslate">
/*
 * 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>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> <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://0.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 &#8230; &#8230; <a href="http://jpauclair.net/2012/01/12/be-an-affiliate-miner/">Continue reading <span class="meta-nav">&#8594;</span></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" />]]></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=584" 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> <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://0.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=584" 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> <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://0.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 &#8230; &#8230; <a href="http://jpauclair.net/2011/12/12/the-king-is-dead-long-live-the-king/">Continue reading <span class="meta-nav">&#8594;</span></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" />]]></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=584" 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=584" 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>
<pre class="brush: as3; title: ; notranslate">
/////////////////////////
// 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>
<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=584" 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=584" 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=584" 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> <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://0.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 class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='584' height='359' src='http://www.youtube.com/embed/CeYCsBIK3uE?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0'></iframe></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> <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://0.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>
