Stable performance test on if/else variants for 20 options

by leichtgewicht
Testing the performance of basic language structures is difficult. This test runs continuously many operations on a complex if/else construct with 20 options for various checks. The running over time ensures the stability of the result 
♥0 | Line 525 | Modified 2012-03-10 09:04:28 | MIT License
play

ActionScript3 source code

/**
 * Copyright leichtgewicht ( http://wonderfl.net/user/leichtgewicht )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/cllu
 */

package {
    import flash.display.AVM1Movie;
    import flash.utils.setTimeout;
    import flash.events.Event;
    import flash.utils.getTimer;
    import flash.text.TextField;
    import flash.display.Sprite;
    public class FlashTest extends Sprite {
        
        private var _text:TextField = new TextField;
        private var _dataSets: Array = [
            [1], // Just the first entry
            [1,2,3], // the first three
            [9,10,11], // the middle three
            [3,11,17], // some three
            [18,19,20],  // end three
            [20], // Just the last entry
            [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] // all
        ];
        private var _operations: Array = [ {
                name: 'byte if/else',
                op: testByte
            }, {
                name: 'byte if/else (reduced)',
                op: testByteReduced
            }, {
                name: 'binary if/else',
                op: testBinary
            }, {
                name: 'binary if/else (reduced)',
                op: testBinaryReduced
            }, {
                name: 'balanced if/else',
                op: testBalanced
            }, {
                name: 'balanced if/else (reduced)',
                op: testBalancedReduced
            }, {
                name: 'linear if/elseif',
                op: testLinear
            }, {
                name: 'switch',
                op: testSwitch
            } ];
        
        private var _count: int = 5000000;
        private var _run: int = 0;
        private var _current: int = 0;
        private var _tMax: Number;
        private var _data: Object = {};
        
        public function FlashTest() {
            addChild( _text );
            _text.width = stage.stageWidth;
            _text.height = stage.stageHeight;
            stage.frameRate = 5;
            _tMax = int(1000/stage.frameRate * 0.5); // Maximal 50% load
            for each( var op: Object in _operations) {
                op.run = 0;
                op.avg = 0;
                op.max = 0;
                op.min = int.MAX_VALUE;
            }
            testRun();
        }
        
        public function testRun():void {
            var result: Object = {}, tTotal: Number = 0.0, i:int;
            
            while( true ) {
                var op: Object = _operations[_current++];
                var dataNo: int = op.run%_dataSets.length;
                var data: Vector.<int>;
                if( _data[dataNo] ) {
                    data = _data[dataNo];
                } else {
                    var dataSet: Array = _dataSets[dataNo];
                    var dataSetLen: int = dataSet.length;
                    data = new Vector.<int>(_count);
                    for( i=0; i<_count; ++i){
                        data[i] = dataSet[i%dataSetLen];
                    }
                    _data[dataNo] = data;
                }

                var t: Number = getTimer();
                op.op(data, _count);
                t = getTimer()-t;
                
                op.min = op.min > t ? t : op.min;
                op.avg = int((op.avg*op.run+t)/(++op.run)*100.0)/100.0;
                op.max = op.max < t ? t : op.max;
                tTotal += t;
                if( _current == _operations.length) {
                    _current = 0;
                }
                if( tTotal > _tMax ) {
                    break;
                }
            }
            
            var min: Number = _operations[0].avg;
            _text.text = "";
            for( i=0; i<_operations.length; ++i) {
                op = _operations[i];
                trace(int(100.0/min*op.avg*100.0)/100.0, "% | ",op.min,"ms/", op.avg, "ms/", op.max, "ms for ", op.name, " ("+ op.run+" runs)");
            }
            
            trace( "\n"+ _count + " operations");
            
            ++_run;
            if( _run < int.MAX_VALUE ) {
                setTimeout(testRun, 80);
            }
        }
        
        private function trace(...args:Array):void {
            for each( var arg: * in args ) {
                if( arg is Number ) {
                    if( arg is int ) {
                        arg = arg+".00";
                    } else {
                        arg = arg.toString(10);
                        if( arg.indexOf(".") == arg.length-2 ) {
                            arg += "0";
                        }
                    }
                }
                _text.appendText(arg);
            }

            _text.appendText("\n");
        }
        
        private function testSwitch(data:Vector.<int>, c:int): void {
            var x: int;
            for( var i:int = 0; i<c; ++i) {
                x = data[i];
                switch(x) {
                    case 1: break;
                    case 2: break;
                    case 3: break;
                    case 4: break;
                    case 5: break;
                    case 6: break;
                    case 7: break;
                    case 8: break;
                    case 9: break;
                    case 10: break;
                    case 11: break;
                    case 12: break;
                    case 13: break;
                    case 14: break;
                    case 15: break;
                    case 16: break;
                    case 17: break;
                    case 18: break;
                    case 19: break;
                    default:break;
                }
            }
        }
        
        private function testLinear(data:Vector.<int>, c:int): void {
            var x: int;
            for( var i:int = 0; i<c; ++i) {
                x = data[i];
                if(x==1) {}
                else if(x==2) {}
                else if(x==3) {}
                else if(x==4) {}
                else if(x==5) {}
                else if(x==6) {}
                else if(x==7) {}
                else if(x==8) {}
                else if(x==9) {}
                else if(x==10) {}
                else if(x==11) {}
                else if(x==12) {}
                else if(x==13) {}
                else if(x==14) {}
                else if(x==15) {}
                else if(x==16) {}
                else if(x==17) {}
                else if(x==18) {}
                else if(x==19) {}
                else {}
            }
        }
        
        private function testBalancedReduced(data:Vector.<int>, c:int): void {
            var x: int;
            for( var i:int = 0; i<c; ++i) {
                x = data[i];
                if(x<13) {
                    if(x<9) {
                        if(x<5) {
                            if(x<3) {
                                if(x==1) {
                                } else { // 2
                                }
                            } else if(x==3) {
                            } else { // 4
                            }
                        } else {
                            if(x<7) {
                                if(x==5) {
                                } else { // 6
                                }
                            } else if(x==7) {
                            } else { // 8
                            }
                        }
                    } else {
                        if(x<11) {
                            if(x==9) {
                            } else { // 10
                            }
                        } else if(x==11) {
                        } else { // 12
                        }
                    }
                } else {
                    if(x<17) {
                        if(x<15) {
                            if(x==13) {
                            } else { // 14
                            }
                        } else if(x==15) {
                        } else { // 16
                        }
                    } else {
                        if(x<19) {
                            if(x==17) {
                            } else { //18
                            }
                        } else if(x==19) {
                        } else { //20
                        }
                    }
                }
            }
        }
        
        private function testBalanced(data:Vector.<int>, c:int): void {
            var x: int;
            for( var i:int = 0; i<c; ++i) {
                x = data[i];
                if(x<13) {
                    if(x<9) {
                        if(x<5) {
                            if(x<3) {
                                if(x==1) {
                                } else { // 2
                                }
                            } else {
                                if(x==3) {
                                } else { // 4
                                }
                            }
                        } else {
                            if(x<7) {
                                if(x==5) {
                                } else { // 6
                                }
                            } else {
                                if(x==7) {
                                } else { // 8
                                }
                            }
                        }
                    } else {
                        if(x<11) {
                            if(x==9) {
                            } else { // 10
                            }
                        } else {
                            if(x==11) {
                            } else { // 12
                            }
                        }
                    }
                } else {
                    if(x<17) {
                        if(x<15) {
                            if(x==13) {
                            } else { // 14
                            }
                        } else {
                            if(x==15) {
                            } else { // 16
                            }
                        }
                    } else {
                        if(x<19) {
                            if(x==17) {
                            } else { //18
                            }
                        } else {
                            if(x==19) {
                            } else { //20
                            }
                        }
                    }
                }
            }
        }

        
        private function testBinary(data:Vector.<int>, c:int): void {
            var x: int;
            for( var i:int = 0; i<c; ++i) {
                x = data[i];
                if(x<17) {
                    if(x<9) {
                        if(x<5) {
                            if(x<3) {
                                if(x==1) {
                                } else { // 2
                                }
                            } else {
                                if(x==3) {
                                } else { // 4
                                }
                            }
                        } else {
                            if(x<7) {
                                if(x==5) {
                                } else { // 6
                                }
                            } else {
                                if(x==7) {
                                } else { // 8
                                }
                            }
                        }
                    } else {
                        if(x<13) {
                            if(x<11) {
                                if(x==9) {
                                } else { // 10
                                }
                            } else {
                                if(x==11) {
                                } else { // 12
                                }
                            }
                        } else {
                            if(x<15) {
                                if(x==13) {
                                } else { // 14
                                }
                            } else {
                                if(x==15) {
                                } else { // 16
                                }
                            }
                        }
                    }
                } else {
                    if(x<19) {
                        if(x==17) {
                        } else { //18
                        }
                    } else {
                        if(x==19) {
                        } else { //20
                        }
                    }
                }
            }
        }

        
        private function testBinaryReduced(data:Vector.<int>, c:int): void {
            var x: int;
            for( var i:int = 0; i<c; ++i) {
                x = data[i];
                if(x<17) {
                    if(x<9) {
                        if(x<5) {
                            if(x<3) {
                                if(x==1) {
                                } else { // 2
                                }
                            } else if(x==3) {
                            } else { // 4
                            }
                        } else {
                            if(x<7) {
                                if(x==5) {
                                } else { // 6
                                }
                            } else if(x==7) {
                            } else { // 8
                            }
                        }
                    } else {
                        if(x<13) {
                            if(x<11) {
                                if(x==9) {
                                } else { // 10
                                }
                            } else if(x==11) {
                            } else { // 12
                            }
                        } else {
                            if(x<15) {
                                if(x==13) {
                                } else { // 14
                                }
                            } else if(x==15) {
                            } else { // 16
                            }
                        }
                    }
                } else {
                    if(x<19) {
                        if(x==17) {
                        } else { //18
                        }
                    } else if(x==19) {
                    } else { //20
                    }
                }
            }
        }

        
        private function testByte(data:Vector.<int>, c:int): void {
            var x: int;
            for( var i:int = 0; i<c; ++i) {
                x = data[i];
                if(x&1) {
                    if(x&2) {
                        if(x&4) {
                            if(x&8) {
                                // 15
                            } else {
                                // 7
                            }
                        } else {
                            if(x&8) {
                                // 11
                            } else {
                                if(x&16){
                                    // 19
                                } else {
                                    // 3
                                }
                            }
                        }
                    } else {
                        if(x&4) {
                            if(x&8) {
                                // 13
                            } else {
                                // 5
                            }
                        } else {
                            if(x&8) {
                                // 9
                            } else {
                                if(x&16) {
                                    // 17
                                } else {
                                    // 1
                                }
                            }
                        }
                    }
                } else {
                    if(x&2) {
                        if(x&4) {
                            if(x&8) {
                                // 14
                            } else {
                                // 6
                            }
                        } else {
                            if(x&8) {
                                // 10
                            } else {
                                if(x&16) {
                                   // 18
                                } else {
                                   // 16
                                }
                            }
                        }
                    } else {
                        if(x&4) {
                            if(x&8) {
                                // 12
                            } else {
                                if(x&16) {
                                    // 20
                                } else {
                                    // 4    
                                }
                            }
                        } else {
                            if(x&8) {
                                // 8
                            } else {
                                // 16
                            }
                        }
                    }
                }
            }
        }

        
        private function testByteReduced(data:Vector.<int>, c:int): void {
            var x: int;
            for( var i:int = 0; i<c; ++i) {
                x = data[i];
                if(x&1) {
                    if(x&2) {
                        if(x&4) {
                            if(x&8) {
                                // 15
                            } else {
                                // 7
                            }
                        } else {
                            if(x&8) {
                                // 11
                            } else if(x&16){
                                // 19
                            } else {
                                // 3
                            }
                        }
                    } else {
                        if(x&4) {
                            if(x&8) {
                                // 13
                            } else {
                                // 5
                            }
                        } else {
                            if(x&8) {
                                // 9
                            } else if(x&16) {
                                // 17
                            } else {
                                // 1
                            }
                        }
                    }
                } else {
                    if(x&2) {
                        if(x&4) {
                            if(x&8) {
                                // 14
                            } else {
                                // 6
                            }
                        } else {
                            if(x&8) {
                                // 10
                            } else if(x&16) {
                               // 18
                            } else {
                               // 16
                            }
                        }
                    } else {
                        if(x&4) {
                            if(x&8) {
                                // 12
                            } else if(x&16) {
                                // 20
                            } else {
                                // 4    
                            }
                        } else if(x&8) {
                            // 8
                        } else {
                            // 16
                        }
                    }
                }
            }
        }        

    }
}