> and suprinsingly I obtain
>
> mode: empty
> testDivide: 8936
> --------------
> mode: standard
> testDivide: 8974
> --------------
> mode: optimized
> testDivide: 9363
> --------------
>
humm going a little further in the tests,
there is one absolute gotcha to know: never use trace while iterating the tests
iterating x times to execute a function is not a real statistic,
you need to run that time sample multiple time if you want to obtain
consistent results
with
standard function testDivide( num:Number ):void
{
var local:Number = num / 2;
}
optimized1 function testDivide( num:Number ):void
{
var local:Number = num * 0.5;
}
optimized2 function testDivide( num:Number ):void
{
var local:Number = num >> 1;
}
optimized3 function testDivide( num:Number ):void
{
var local:Number = num >>> 1;
}
I can obtain that
var t:Benchmarks = new Benchmarks( 10000000, true ); //10.000.000
t.runStatistics( 5, "testDivide" );
-------------------------------
standard testDivide - min: 875, average: 1199.8, max: 1474
optimized1 testDivide - min: 1392, average: 1519 , max: 1698
optimized2 testDivide - min: 768, average: 802.8, max: 839
optimized3 testDivide - min: 2495, average: 2562.6, max: 2671
-------------------------------
var t:Benchmarks = new Benchmarks( 1000000, true ); //1.000.000
t.runStatistics( 5, "testDivide" );
-------------------------------
standard testDivide - min: 63, average: 92.2, max: 113
optimized1 testDivide - min: 105, average: 125.4, max: 141
optimized2 testDivide - min: 54, average: 61 , max: 71
optimized3 testDivide - min: 216, average: 241.2, max: 270
-------------------------------
var t:Benchmarks = new Benchmarks( 100000, true ); //100.000
t.runStatistics( 5, "testDivide" );
-------------------------------
standard testDivide - min: 7, average: 13.6, max: 24
optimized1 testDivide - min: 9, average: 13.6, max: 18
optimized2 testDivide - min: 5, average: 8.8, max: 12
optimized3 testDivide - min: 21, average: 28 , max: 40
-------------------------------
note:
- a little too few iteration and you could obtain negatives number
which flaw the test
- I used 5 samples, but you could go for 10, 15 and more (till flash
break ;)) the results stay consistent
what we learn with those stats
(value *.5) is slower than (value/2)
(value>>>1) is slower than (value>>1)
the standard way of doing a division is not that bad,
the bitshift win overwall
I just forgot my log/pwd for OSFlash wiki, but here the code used
--------------------------
package test
{
import flash.utils.getTimer;
public class Benchmarks
{
public namespace empty = "empty";
public namespace standard = "standard";
public namespace optimized1 = "optimized1";
public namespace optimized2 = "optimized2";
public namespace optimized3 = "optimized3";
public var mode:Namespace = empty;
private var _maxOptimizedTest:int = 3;
private var _iteration:int
private var _emptyTestTime:Object;
private var _substractEmptyTest:Boolean;
private var _showEmptyTest:Boolean;
private var _separator:String;
private var _logs:String;
private var _statistics:Object;
private var _keepStats:Boolean;
public function Benchmarks( iteration:int = 10000000,
substractEmptyTest:Boolean = false,
showEmptyTest:Boolean = false )
{
_keepStats = false;
_logs = "";
_statistics = {};
_resetStats();
_emptyTestTime = {};
_separator = "-------------------------------";
_iteration = iteration;
_substractEmptyTest = substractEmptyTest;
_showEmptyTest = showEmptyTest;
}
private function _resetStats():void
{
_statistics.standard = {};
for( var i:int = 1; i<_maxOptimizedTest+1; i++ )
{
_statistics["optimized"+i] = {};
}
}
private function _addMethodToStats( method:String ):void
{
if( _statistics.standard[ method ] != undefined )
{
//trace( "method " + method + " already in statistics" );
return;
}
_statistics.standard[ method ] = [];
for( var i:int = 1; i<_maxOptimizedTest+1; i++ )
{
_statistics["optimized"+i][ method ] = [];
}
}
private function _showStats():void
{
//standard testDivide - min: 0, average:5, max:10
var samples:Array;
var min:Number;
var average:Number;
var max:Number;
var accumulate:Function = function( data:Array ):Number
{
var sum:Number = 0;
for( var i:int = 0; i<data.length; i++ )
{
sum += data[i];
}
return sum;
}
for( var ns:String in _statistics )
{
for( var method:String in _statistics[ns] )
{
samples = _statistics[ns][method];
samples.sort( Array.NUMERIC );
min = samples[0];
max = samples[ samples.length-1 ];
average = accumulate( samples ) / samples.length;
log( ns +" "+method +" - min: "+min+", average:
"+average+", max: "+max );
}
}
}
private function _runAll( method:String = "" ):void
{
mode = standard;
run( method );
mode = optimized1;
run( method );
mode = optimized2;
run( method );
mode = optimized3;
run( method );
}
public function log( message:String ):void
{
_logs += message + "\n";
}
public function runAll( ...methods ):void
{
for( var i:int=0; i<methods.length; i++ )
{
if( _keepStats )
{
_addMethodToStats( methods[i] );
}
_runAll( methods[i] );
log( _separator );
}
if( !_keepStats )
{
trace( _logs );
}
}
public function runStatistics( samples:int, ...methods ):void
{
_keepStats = true;
for( var i:int=0; i<samples; i++ )
{
runAll.apply( this, methods );
}
_logs = "";
log( _separator );
_showStats();
log( _separator );
trace( _logs );
}
public function run( method:String = "", showLog:Boolean = false ):void
{
if( method == "" )
{
log( "test method is empty" );
return;
}
try
{
var exists:* = mode::[method];
}
catch( e:Error )
{
if( e.errorID == 1065 )
{
//log( "test method \""+method+"\" does not exists
in ["+mode+"]" );
return;
}
}
if( (mode != empty) && !_emptyTestTime[method] )
{
var original:Namespace = mode;
mode = empty;
run( method );
mode = original;
}
var i:Number;
var max:Number = _iteration;
var t1:int = getTimer();
for( i=0; i<max; i++ )
{
mode::[method]( i );
}
var t2:int = getTimer();
if( mode == empty )
{
_emptyTestTime[method] = (t2-t1);
}
var result:int;
if( _substractEmptyTest && (_emptyTestTime[method] != 0) )
{
result = ((t2-t1)-_emptyTestTime[method]);
}
else
{
result = (t2-t1);
}
if( !_showEmptyTest && (mode == empty) )
{
return;
}
if( _keepStats && (mode != empty) )
{
_statistics[ mode.toString() ][ method ].push( result );
}
log( mode + " " + method+": " + result );
log( _separator );
if( showLog )
{
trace( _logs );
}
}
empty function testDivide( num:Number ):void
{
}
standard function testDivide( num:Number ):void
{
var local:Number = num / 2;
}
optimized1 function testDivide( num:Number ):void
{
var local:Number = num * 0.5;
}
optimized2 function testDivide( num:Number ):void
{
var local:Number = num >> 1;
}
optimized3 function testDivide( num:Number ):void
{
var local:Number = num >>> 1;
}
}
}
--------------------------
zwetan
_______________________________________________
osflash mailing list
[email protected]
http://osflash.org/mailman/listinfo/osflash_osflash.org