Performance test for reading variable ints of a bytearray
♥0 |
Line 377 |
Modified 2011-09-15 01:49:01 |
MIT License
archived:2017-03-20 08:26:51
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/ozwn
*/
package {
import flash.utils.getTimer;
import flash.text.TextFormat;
import flash.utils.Endian;
import flash.utils.ByteArray;
import flash.display.Sprite;
public class FlashTest extends Sprite {
public function FlashTest() {
addChild(field);
field.defaultTextFormat = new TextFormat("Courier", 10);
field.width = stage.stageWidth;
field.height = stage.stageHeight;
basicAssumptions();
flagTests();
testFunctionality();
testPerformance();
}
public function basicAssumptions():void {
text("\nBasic Data storage assumption");
var byteArray:ByteArray = new ByteArray();
byteArray.endian = Endian.LITTLE_ENDIAN;
byteArray.writeByte(255); // 11111111
byteArray.writeByte(255); // 11111111
byteArray.writeByte(255); // 11111111
byteArray.writeByte(255); // 11111111
byteArray.position = 0;
t( "11111111111111111111111111111111", byteArray.readInt() );
byteArray.position = 0;
byteArray.writeByte(128); // 00000001
byteArray.writeByte(0); // 00000000
byteArray.writeByte(0); // 00000000
byteArray.writeByte(0); // 00000000
byteArray.position = 0;
t( "00000001000000000000000000000000", byteArray.readInt() );
byteArray.position = 0;
byteArray.writeByte(127); // 11111110
byteArray.writeByte(0); // 00000000
byteArray.writeByte(0); // 00000000
byteArray.writeByte(0); // 00000000
byteArray.position = 0;
t( "11111110000000000000000000000000", byteArray.readInt() );
byteArray.position = 0;
byteArray.writeByte(0); // 00000000
byteArray.writeByte(128); // 00000001
byteArray.writeByte(0); // 00000000
byteArray.writeByte(0); // 00000000
byteArray.position = 0;
t( "00000000000000010000000000000000", byteArray.readInt() );
byteArray.position = 0;
byteArray.writeByte(0); // 00000000
byteArray.writeByte(127); // 11111110
byteArray.writeByte(0); // 00000000
byteArray.writeByte(0); // 00000000
byteArray.position = 0;
t( "00000000111111100000000000000000", byteArray.readInt() );
byteArray.position = 0;
byteArray.writeByte(0); // 00000000
byteArray.writeByte(0); // 00000000
byteArray.writeByte(127); // 11111110
byteArray.writeByte(0); // 00000000
byteArray.position = 0;
t( "00000000000000001111111000000000", byteArray.readInt() );
byteArray.position = 0;
byteArray.writeByte(0); // 00000000
byteArray.writeByte(0); // 00000000
byteArray.writeByte(128); // 00000001
byteArray.writeByte(0); // 00000000
byteArray.position = 0;
t( "00000000000000000000000100000000", byteArray.readInt() );
byteArray.position = 0;
byteArray.writeByte(0); // 00000000
byteArray.writeByte(0); // 00000000
byteArray.writeByte(0); // 00000000
byteArray.writeByte(127); // 11111110
byteArray.position = 0;
t( "00000000000000000000000011111110", byteArray.readInt() );
byteArray.position = 0;
byteArray.writeByte(0); // 00000000
byteArray.writeByte(0); // 00000000
byteArray.writeByte(0); // 00000000
byteArray.writeByte(128); // 00000001
byteArray.position = 0;
t( "00000000000000000000000000000001", byteArray.readInt() );
text("\nTest Numbers");
byteArray.position = 0;
byteArray.writeByte(127); // 11111110
byteArray.writeByte(0); // 00000000
byteArray.writeByte(0); // 00000000
byteArray.writeByte(0); // 00000000
byteArray.position = 0;
t( "11111111000000000000000000000000", byteArray.readInt() );
byteArray.position = 0;
byteArray.writeByte(255); // 11111111
byteArray.writeByte(63); // 11111100
byteArray.writeByte(0); // 00000000
byteArray.writeByte(0); // 00000000
byteArray.position = 0;
t( "11111111111111000000000000000000", byteArray.readInt() );
byteArray.position = 0;
byteArray.writeByte(255); // 11111111
byteArray.writeByte(255); // 11111111
byteArray.writeByte(31); // 11111000
byteArray.writeByte(0); // 00000000
byteArray.position = 0;
t( "11111111111111111111100000000000", byteArray.readInt() );
byteArray.position = 0;
byteArray.writeByte(255); // 11111111
byteArray.writeByte(255); // 11111111
byteArray.writeByte(255); // 11111111
byteArray.writeByte(15); // 11110000
byteArray.position = 0;
t( "11111111111111111111111111110000", byteArray.readInt() );
byteArray.position = 0;
byteArray.writeByte(255); // 11111111
byteArray.writeByte(255); // 11111111
byteArray.writeByte(255); // 11111111
byteArray.writeByte(255); // 11111111
byteArray.position = 0;
t( "11111111111111111111111111111111", byteArray.readInt() );
text("\nreadByte/writeByte important for the last part of the reader");
byteArray.position = 0;
byteArray.writeByte(128); // 00000001
byteArray.position = 0;
t( "00000001", byteArray.readByte() );
byteArray.position = 0;
byteArray.writeByte(127); // 11111110
byteArray.position = 0;
t( "11111110", byteArray.readByte() );
byteArray.position = 0;
byteArray.writeByte(15); // 11110000
byteArray.position = 0;
t( "11110000", byteArray.readByte() );
}
public function flagTests():void {
text("\nByte checks for each level");
binChk(-1,128); // first byte check
binChk(-1,32768); // second byte check
binChk(-1,8388608); // third byte check
binChk(-1,-2147483648); // fourth byte check
}
public function prepareTestNumbers(byteArray:ByteArray): int {
var amountNumbers: int = 0;
// Number 11111110000000000000000000000000 = 127
byteArray.writeByte(127); // 11111110
++amountNumbers;
// Number 00000000000000000000000000000000 = 0
byteArray.writeByte(0); // 00000000
++amountNumbers;
// Number 11111111111111000000000000000000 = 16383
byteArray.writeByte(255); // 11111111
byteArray.writeByte(127); // 11111110
++amountNumbers;
// Number 11111111111111111111100000000000 = 2097151
byteArray.writeByte(255); // 11111111
byteArray.writeByte(255); // 11111111
byteArray.writeByte(127); // 11111110
++amountNumbers;
// Number 11111111111111111111111111110000 = 268435455
byteArray.writeByte(255); // 11111111
byteArray.writeByte(255); // 11111111
byteArray.writeByte(255); // 11111111
byteArray.writeByte(127); // 11111110
++amountNumbers;
// Number 11111111111111111111111111111111 = -1
byteArray.writeByte(255); // 11111111
byteArray.writeByte(255); // 11111111
byteArray.writeByte(255); // 11111111
byteArray.writeByte(255); // 11111111
byteArray.writeByte(15); // 11110000
++amountNumbers;
return amountNumbers;
}
public function testFunctionality():void {
text( "\nFunctionality test");
var valuesA: Vector.<int>= new Vector.<int>;
var valuesB: Vector.<int> = new Vector.<int>;
var bytes: ByteArray = new ByteArray();
bytes.endian = Endian.LITTLE_ENDIAN;
var nums: int = prepareTestNumbers(bytes);
var i: int;
bytes.position = 0;
for( i= 0; i < nums; ++i ) {
valuesA.push(readVariableLengthOld(bytes));
}
bytes.position = 0;
for( i= 0; i < nums; ++i ) {
valuesB.push(readVariableLengthIntDiscussion(bytes));
}
for( i= 0; i < nums; ++i ) {
var same: Boolean = valuesA[i] == valuesB[i];
if( same ) {
text( "ok: "+valuesA[i]+" == "+valuesB[i]+ " = "+same );
} else {
text( "error: "+valuesA[i]+" == "+valuesB[i]+ " = "+same );
}
}
}
public function testPerformance():void {
text( "\nPerformance test");
var bytes: ByteArray = new ByteArray();
bytes.endian = Endian.LITTLE_ENDIAN;
var nums: int = prepareTestNumbers(bytes);
var i: int;
var j: int;
const count: int = 100000;
var t:Number;
t = getTimer();
for( j=0; j<count;++j) {
bytes.position = 0;
for( i= 0; i < nums; ++i ) {
readVariableLengthOld(bytes);
}
}
text( (getTimer()-t)+"ms for the old implementation");
t = getTimer();
for( j=0; j<count;++j) {
bytes.position = 0;
for( i= 0; i < nums; ++i ) {
readVariableLengthOldTest(bytes);
}
}
text( (getTimer()-t)+"ms for the old test implementation");
t = getTimer();
for( j=0; j<count;++j) {
bytes.position = 0;
for( i= 0; i < nums; ++i ) {
readVariableLengthIntDiscussion(bytes);
}
}
text( (getTimer()-t)+"ms for the new implementation");
const l: int = bytes.length-3;
t = getTimer();
for( j=0; j<count;++j) {
bytes.position = 0;
for( i= 0; i < nums; ++i ) {
readVariableLengthInt(bytes,l);
}
}
text( (getTimer()-t)+"ms for the newer implementation");
t = getTimer();
for( j=0; j<count;++j) {
bytes.position = 0;
for( i= 0; i < nums; ++i ) {
readVariableLengthUnsignedShort(bytes);
}
}
text( (getTimer()-t)+"ms for the short implementation");
}
public function readVariableLengthOld( byteArray:ByteArray ):int {
var result: int = byteArray.readUnsignedByte();
if ((result & 0x00000080)) {
result = result & 0x0000007f | byteArray.readUnsignedByte() << 7;
if ((result & 0x00004000)) {
result = result & 0x00003fff | byteArray.readUnsignedByte() << 14;
if ((result & 0x00200000)) {
result = result & 0x001fffff | byteArray.readUnsignedByte() << 21;
if ((result & 0x10000000)) {
result = result & 0x0fffffff | byteArray.readUnsignedByte() << 28;
}
}
}
}
return result;
}
public function readVariableLengthOldTest( byteArray:ByteArray ):int {
var result: int = byteArray.readUnsignedByte();
if ((result & 0x00000080)) {
result = result & 0x0000007f | byteArray.readUnsignedByte() << 7;
if ((result & 0x00004000)) {
result = result & 0x00003fff | byteArray.readUnsignedByte() << 14;
if ((result & 0x00200000)) {
result = result & 0x001fffff | byteArray.readUnsignedByte() << 21;
if ((result & 0x10000000)) {
result = result & 0x0fffffff | byteArray.readByte() << 28;
}
}
}
}
return result;
}
public function readVariableLengthInt( byteArray:ByteArray, bytesTotalMinus3:int ):int {
var temp: int;
var result: int = byteArray.readUnsignedByte();
// result contains 11111110000000000000000000000000
if( result & 0x80 ) {
if( byteArray.position < bytesTotalMinus3 ) {
// reading 11111110000000000000000000000000
// putting it seven aside
temp = byteArray.readInt();
result = result & 0x7f | ((temp & 0x7f) << 7);
// contains 11111111111111000000000000000000
if( temp & 0x80 ) {
// reading 00000000111111100000000000000000
// putting it six aside
result += (temp & 0x7f00) << 6;
// contains 11111111111111111111100000000000
if( temp & 0x8000 ) {
// reading 00000000000000001111111000000000
// putting it three aside
result += (temp & 0x7f0000) << 5;
// contains 11111111111111111111111111110000
if( temp & -0x800000 ) {
// reading 00000000000000000000000011110000
result += (temp & 0x7f000000) << 4;
// contains 11111111111111111111111111111111 (*yeah!*)
} else {
--byteArray.position;
}
} else {
byteArray.position -= 2;
}
} else {
byteArray.position -= 3;
}
} else {
result = result & 0x0000007f | byteArray.readUnsignedByte() << 7;
if ((result & 0x00004000)) {
result = result & 0x00003fff | byteArray.readUnsignedByte() << 14;
if ((result & 0x00200000)) {
result = result & 0x001fffff | byteArray.readUnsignedByte() << 21;
if ((result & 0x10000000)) {
result = result & 0x0fffffff | byteArray.readUnsignedByte() << 28;
}
}
}
}
}
return result;
}
public function readVariableLengthIntDiscussion( byteArray:ByteArray ):int {
var temp: int = byteArray.readInt();
var result: int = temp & 0x7f;
// result contains 11111110000000000000000000000000
if( temp & 0x80 ) {
// reading 00000000111111100000000000000000
// > ... this bit has been used by the marker bit before
// putting it one aside
result += (temp & 0x7f00) >> 1;
// contains 11111111111111000000000000000000
if( temp & 0x8000 ) {
// reading 00000000000000001111111000000000
// >> ... now we've had 2 marker bits
// putting it two aside
result += (temp & 0x7f0000) >> 2;
// contains 11111111111111111111100000000000
if( temp & 0x800000 ) {
// reading 00000000000000000000000011111110
// >>> ... and now 3 marker bit
// putting it three aside
result += (temp & 0x7f000000) >> 3;
// contains 11111111111111111111111111110000
if( temp & -0x80000000 ) {
// reading 11110000000000000000000000000000
// <<<<<<<<<<<<<<<<<<<<<<<<<<<< // (28 = 7 value bits in 4 bytes);
result += byteArray.readUnsignedByte() << 28;
// contains 11111111111111111111111111111111 (*yeah!*)
}
} else {
--byteArray.position;
}
} else {
byteArray.position -= 2;
}
} else {
byteArray.position -= 3;
}
return result;
}
public function readVariableLengthUnsignedShort( byteArray:ByteArray ):int {
var temp: int = byteArray.readUnsignedShort();
var result: int = temp & 0x7f;
if( temp & 0x80 ) {
result = result | (temp & 0x7f00) >> 1;
if( temp & 0x8000 ) {
temp = byteArray.readUnsignedShort();
result = result | (temp & 0x7f) << 6;
if( temp & 0x80 ) {
result = result | (temp & 0x7f00) << 5;
if( temp & 0x8000 ) {
result = result | byteArray.readUnsignedByte() << 28;// (28 = 7*3);
}
} else {
byteArray.position -= 1;
}
}
} else {
byteArray.position -= 1;
}
return result;
}
}
}
import flash.text.TextField;
const field: TextField = new TextField();
function binChk(value:int,mask:int):void {
field.appendText( value.toString(10) + " & " + mask.toString(10)+" = "+((value&mask)!=0)+"\n");
}
function t(bin:String, no:int ):void {
var str: String = no.toString(10);
while( str.length < 11 ) {
str = " "+str;
}
var str2: String = no.toString(16);
while( str2.length < 11 ) {
str2 = " "+str2;
}
field.appendText(bin+"..."+str+"..."+str2+"\n");
}
function text(txt:String):void {
field.appendText(txt+"\n");
}