I have run some test about haXe iterators. Iterators provide a very nice abstraction but their speed when used in for loops was a big disappointment.
I tested it by creating many different ways to calculate the fibonacci series
Infinite Fibonacci Iterator:
class FibIter1 {
var val : UInt;
var nextVal : UInt;
public function new() {
val = 0;
nextVal = 1;
}
public inline function hasNext() : Bool {
return true;
}
public inline function next() : UInt {
var tmpVal = val;
val = nextVal;
nextVal = tmpVal + val;
return tmpVal;
}
}
Bounded Fibonacci Iterator:
class FibIter2 {
var val : UInt;
var nextVal : UInt;
var count : UInt;
public function new( count : UInt ) {
val = 0;
nextVal = 1;
this.count = count;
}
public inline function hasNext() : Bool {
return count != 0;
}
public inline function next() : UInt {
var tmpVal = val;
val = nextVal;
nextVal += tmpVal;
count--;
return tmpVal;
}
}
Test code:package ;
import flash.Lib;
import org.flashdevelop.utils.FlashConnect;
class Main
{
inline static var Test = 5;
static function main() {
var startTime = Lib.getTimer();
var acc = 0;
for ( i in 0...99999 ) {
if ( Test == 1 ) {
// ********************************
// Test 1
// Infinite Iterator + Manual Break
// ********************************
var count : UInt = 99;
for ( a in new FibIter1() ) {
if ( count-- == 0 ) break;
acc += a;
}
}else if ( Test == 2 ) {
// ********************************
// Test 2
// Bounded iterator
// ********************************
for ( a in new FibIter2(99) ) {
acc += a;
}
}else if ( Test == 3 ) {
// ********************************
// Test 3
// Manual algorithm using while
// ********************************
var val : UInt = 0;
var nextVal : UInt = 1;
var count : UInt = 99;
while ( count-- != 0 ) {
acc += val;
var tmpVal = val;
val = nextVal;
nextVal += tmpVal;
}
}else if ( Test == 4 ) {
// ********************************
// Test 4
// Manual algorithm using for
// ********************************
var val : UInt = 0;
var nextVal : UInt = 1;
for ( i in 0...99 ) {
acc += val;
var tmpVal = val;
val = nextVal;
nextVal += tmpVal;
}
}else if ( Test == 5 ) {
// ********************************
// Test 5
// Bounded iterator using while
// ********************************
var iter = new FibIter2(99);
while ( iter.hasNext() ) {
acc += iter.next();
}
}
}
FlashConnect.trace(acc);
var endTime = Lib.getTimer();
FlashConnect.trace( "Test " + Test + ": " + (endTime - startTime) );
}
}
Results (In haXe 2.05):
Test 1: 5893ms
Test 2: 5692ms
Test 3: 125ms
Test 4: 131ms
Test 5: 136ms
Conclusions:
After being disappointed by the results of the for expression I decided to check the generated bytecode: apparently the haXe compiler wont inline iterator methods in a for loop. The test 5 shows that the iterator class can be pretty fast if it is correctly inlined.
I can't think of a good reason why the compiler shouldn't be able to inline the iterator methods, which can be a good thing, because if there is no good reason then maybe in future versions of haxe for will inline too.
No comments:
Post a Comment