STUDIO B12  Büro für digitale Kommunikation  T  0531 28 853 78 0  E  info@studio-b12.de

Quicktip: Schnellere Math.abs() Funktion

Ein kleiner Vergleich bringt es ans Licht: die Funktionalität von Math.abs() kann in AS3 durch eigene Funktionen deutlich schneller realisiert werden. Dazu habe ich eine kleine Testklasse geschrieben, die verschiedene Methoden vergleicht:

package de.sb12.matthias.playground.mathabs {
	import flash.display.Sprite;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.utils.getTimer;
 
	/**
	 * creation date: 07.08.2009
	 * @author Matthias Dehmel
	 *
	 * modified by $Author$ on $Date$
	 * @version $Id$
	 */
	public class MathAbsPerformance extends Sprite {
		private const TESTRUNS : uint = 200000;
		private var _log : TextField;
 
		public function MathAbsPerformance() {
			_log = new TextField( );
			_log.width = 500;
			_log.autoSize = TextFieldAutoSize.LEFT;
			_log.wordWrap = true;
			_log.multiline = true;
			_log.x = _log.y = 20;
			addChild(_log);
 
			mathAbs();
			manualMathAbs();
			inlineManualMathAbs();
			bitshift();
		}
 
		private function mathAbs() : void {
			var start : Number = getTimer();
			var num : Number;
			var i : int = 0;
			for (i; i < TESTRUNS ; i++)
				num = Math.abs( 5 );
 
			log('Math.abs', getTimer( ) - start );
		}
 
		private function manualMathAbs() : void {
			var start : Number = getTimer();
			var num : Number;
			var i : int = 0;
			for (i; i < TESTRUNS ; i++)
				num = abs( 5 );
 
			log('manual abs', getTimer( ) - start );
		}
 
		private function abs( value : Number ) : Number {
			return ( value < 0 ) ? -value : value;
		}
 
		private function inlineManualMathAbs() : void {
			var start : Number = getTimer();
			var num : Number = 5;
			var i : int = 0;
			for (i; i < TESTRUNS ; i++)
				num = ( num < 0 ) ? -num : num;		
 
			log('manual inline abs', getTimer( ) - start );
		}
 
		private function bitshift() : void {
			var start : Number = getTimer();
			var num : Number = 5;
			var i : int = 0;
			for (i; i < TESTRUNS ; i++)
                                   num = ( num^( num >> 31 ) ) - ( num >> 31 );
 
			log('bitshift', getTimer( ) - start );
		}
 
		private function log( type : String, time : uint ) : void {
			_log.appendText( '\n' + type + ': ' + time.toString() + 'ms' );
		}
	}
}

Folgende verschiedene Möglichkeiten habe ich getestet:

1. Math.abs(): Der normale Aufruf über die mitgelieferte Math-Klasse
2. eigene abs()-Funktion: stellt die gleiche Funktionalität wie Math.abs() bereit
3. eigene abs()-Funktion als inline code: dasselbe wie unter 2., nur dass keine extra Funktion aufgerufen wird
4. Bitshift-Operation: stellt die gleiche Funktionalität wie Math.abs() bereit

Folgende Ergebnisse habe ich dabei erzielt (200.000 Durchläufe):

1. Math.abs(): 23ms
2. eigene abs()-Funktion: 18ms
3. eigene abs()-Funktion als inline code: 1ms
4. Bitshift-Operation: 2ms

Wenn es also um zeitkritische Berechnungen geht, würde ich immer dazu raten in der relevanten Funktion eine eigene Math.abs()-Implementierung als inline code zu integrieren,da diese mitunter ~23x schneller ist als die Flash-interne Implementierung.

Bookmark and Share

Dein Kommentar