JavaScript Typed Arrays
Posted by Alistair Macdonald
You probably know by now that JavaScript is getting a lot of upgrades at the moment. One of the upgrades that WebGL is bringing along for the ride is JavaScript Typed Arrays.
A JavaScript Typed Array is very quick! It exists as a fixed block of memory that can be accessed with JavaScript, where as a regular JS Array is inherently very slow, being a hash lookup. There are a few different kinds of JS Typed Array like Float32Array, Int8Array, and they are designed to work quickly with binary data for use with WebGL. But you can use them for anything.
Read more about JavaScript Typed Arrays here: JS Typed Arrays on MDC
Note:
A JavaScript Typed Array will only let you store “one type” of variable within it, you can not mix strings and floats. A JavaScript Typed array will not allow you to change the size of the array after instantiation.
Regular vs. Typed
Here are the results of a simple test between a regular JavaScript array, and a Float32Array in Firefox4 Beta1 in milliseconds per operation on an array with a length of 100-million indices. The test was run on Win7 64Bit, 4GB Ram, Dual-Core 1.30Ghz Intel U7300. I ran this test about 8 times and used the lowest numbers for each, so it should probably be noted that the Regular JS Array Write test frequently goes above 10 seconds and causes the slow-script dialog.
Operation | Regular Array | Float32Array |
---|---|---|
Write | 8947 | 1455 |
Read | 1948 | 1109 |
Loop-Copy | > 10,000 ms | 1969 |
Slice-Copy | 1125 | 503 |
The Scripts
These are the two scripts I ran to get the results above. You can run these tests on your browser now by clicking here: 1) JavaScript Typed Array Test, 2) Regular JavaScript Array Test. (You will need more than 2Gb of ram to test these.)
// Float32Array
var ary32 = new Float32Array(100000000);
var start = +new Date();
for(var i=0, l=ary32.length; i < l; i++){
ary32[i] = 0.1234567890123456;
}
alert( "Write: " + ( + new Date() - start ) );
// 1455ms
var val = 0;
var start = +new Date();
for(var i=0, l=ary32.length; i < l; i++){
val = ary32[i];
}
alert( "Read: " + ( +new Date() - start ) );
// 1109ms
var start = +new Date();
var ary32Copy = new Float32Array(ary32.length);
for(var i=0, l=ary32.length; i < l; i++){
ary32Copy[i] = ary32[i];
}
alert( "Loop Copy: " + ( + new Date() - start ) );
// 1969ms
var start = +new Date();
var ary32SliceCopy = new Float32Array(ary32.slice(0, ary32.length));
alert( "Slice Copy: " + ( + new Date() - start ) );
// 503ms
// Regular JavaScript Array
var ary = new Array(100000000);
var start = +new Date();
for(var i=0, l=ary.length; i < l; i++){
ary[i] = 0.1234567890123456;
}
alert( "Write: " + ( + new Date() - start ) );
// 8947
var val = 0;
var start = +new Date();
for(var i=0, l=ary.length; i < l; i++){
val = ary[i];
}
alert( "Read: " + ( +new Date() - start ) );
// 1948
var start = +new Date();
var aryCopy = new Array(ary.length);
for(var i=0, l=ary.length; i < l; i++){
aryCopy[i] = ary[i];
}
alert( "Loop Copy: " + ( + new Date() - start ) );
// SCRIPT STOPS WITHOUT ERROR MESSAGE!!
var start = +new Date();
var arySliceCopy = new Array(ary.slice(0, ary.length));
alert( "Slice Copy: " + ( + new Date() - start ) );
//1125