Vector vs. ByteArray
Which is the fastest way to store data: Vector
or ByteArray
? Given that you can upload both types to Stage3D
in Flash Player 11, this question has never been more relevant. So which should you use to maximize your app’s speed? Read on for the performance testing.
To test the two classes out, I made an app that simply fills a Vector
and a ByteArray
using various approaches:
Vector
index ([]
) operatorByteArray
index ([]
) operatorByteArray.writeByte
ByteArray.writeInt
ByteArray.writeDouble
I used these to fill out these structures:
Vector.<int>
Vector.<Number>
ByteArray
of bytesByteArray
of intsByteArray
of Numbers/doubles
Here is the source code for the test:
package { import flash.display.Sprite; import flash.text.TextField; import flash.text.TextFieldAutoSize; import flash.utils.ByteArray; import flash.utils.getTimer; public class VectorVsByteArray extends Sprite { private var logger:TextField = new TextField(); private function row(...cols): void { logger.appendText(cols.join(",")+"\n"); } public function VectorVsByteArray() { logger.autoSize = TextFieldAutoSize.LEFT; addChild(logger); var SIZE:int = 1000000; var beforeTime:int; var afterTime:int; var i:int; var vi:Vector.<int>; var vf:Vector.<Number>; var ba:ByteArray; vi = new Vector.<int>(SIZE); vf = new Vector.<Number>(SIZE); ba = new ByteArray(); row("Test", "Time"); beforeTime = getTimer(); for (i = 0; i < SIZE; ++i) { vi[i] = 33; } afterTime = getTimer(); row("Vector int", (afterTime-beforeTime)); ba.length = SIZE; ba.position = 0; beforeTime = getTimer(); for (i = 0; i < SIZE; ++i) { ba[i] = 33; } afterTime = getTimer(); row("ByteArray byte (index)", (afterTime-beforeTime)); ba.length = 0; ba.position = 0; beforeTime = getTimer(); for (i = 0; i < SIZE; ++i) { ba.writeByte(33); } afterTime = getTimer(); row("ByteArray byte (writeByte)", (afterTime-beforeTime)); ba.length = 0; ba.position = 0; beforeTime = getTimer(); for (i = 0; i < SIZE; ++i) { ba.writeInt(33); } afterTime = getTimer(); row("ByteArray int (writeInt)", (afterTime-beforeTime)); beforeTime = getTimer(); for (i = 0; i < SIZE; ++i) { vf[i] = 33.3; } afterTime = getTimer(); row("Vector Number", (afterTime-beforeTime)); ba.length = 0; ba.position = 0; beforeTime = getTimer(); for (i = 0; i < SIZE; ++i) { ba.writeDouble(33.3); } afterTime = getTimer(); row("ByteArray Number (writeDouble)", (afterTime-beforeTime)); } } }
I ran this test on the following environment:
- Flex SDK (MXMLC) 4.5.1.21328, compiling in release mode (no debugging or verbose stack traces)
- Release version of Flash Player 11.1.102.63
- 2.4 Ghz Intel Core i5
- Mac OS X 10.7.3
And got these results:
Test | Time |
---|---|
Vector int | 16 |
ByteArray byte (index) | 34 |
ByteArray byte (writeByte) | 69 |
ByteArray int (writeInt) | 63 |
Vector Number | 18 |
ByteArray Number (writeDouble) | 90 |
Given this performance data, we can draw some conclusions:
Vector
is 2-6x faster at writing out data thanByteArray
- Using the index operator with
ByteArray
is much faster thanByteArray.writeByte
- Writing
Number
/double values is slower than bytes or ints, especially viaByteArray
One caveat to the above results is that the Alchemy opcodes can be used to much more efficiently use ByteArrays
. Unfortunately, these opcodes are not available in pure AS3 application so you’ll need to use a third-party tool like Apparat or language like HaXe to get access to them. Beware though as these opcodes will no longer be supported in the upcoming release of Flash Player 11.2.
So for now the best pure AS3 method of storing lots of data very quickly is Vector
. By a lot.
Spot a bug? Have a suggestion? Post a comment!
#1 by Rackdoll on March 26th, 2012 ·
Very VERY interesting find.
One would presume bytearray will win this bec of bytes…
Glad you did this test. Now i need to rewrite my codes… ugh :)
keep on the greatness!
Ciao
Rackdoll
#2 by Matt Lockyer on March 26th, 2012 ·
I too will have to refactor my code.
This comes hot on the heels of your post about upload speed to the vertexBuffer… which had me thinking ByteArray was the way to go.
I agree with your comment about Alchemy, however if you’ve been following the debate, you will know that Alchemy opcodes are restricted in FP 11.2 and Air 3.2 since Alchemy 2 is a paid product and the swfs using these fast memory codes will need to be signed (licensed from Adobe).
In my opinion, this ruins the Flash community and causes a HUGE divide.
I hope Adobe make this technology accessible for Indies for free.
#3 by jackson on April 2nd, 2012 ·
You only need a “premium features” license if you use Alchemy/domain memory and
Stage3D
according to this Adobe post.#4 by hexagonstar on March 27th, 2012 ·
Excellent AS3 performance hints here, as always!
#5 by ben w on March 29th, 2012 ·
for the most part buffers go unmodified after creation so I wouldn’t be in a massive hurry to convert any code just yet.
Although highly improbable, it would be much more interesting to see if there is any impact on performance between the two.
i.e. once uploaded does it make any difference to the speed of the drawTriangles call.
Would geometry stored with byte arrays for its index buffers and vertex buffers perform any different to its vector counterpart, I see no reason why it would though.
In defence of bytearray as a good format for 3d in flash, you can compress it and store it on disk easily. You can even store your index buffer and vertex data all in the same bytearray I believe leading to ridiculously fast loading from disk and uploading to gpu, no parsing required..so any overhead is only a one off. (assuming you are rolling our your own custom formats for geometry)
b
#6 by jackson on April 2nd, 2012 ·
There are definitely many good reasons to use
ByteArray
and you’ve hit on several here. The article is only intended to test the performance of them outside of any particular usage likeStage3D
. As for speed differences after uploading, I highly doubt there are any. Graphics cards don’t know about the AS3Vector
type, so there’s definitely a conversion going on at upload time. To see the cost of this, check out my Stage3D Upload Speed Tester article.#7 by gloomyBrain on April 3rd, 2012 ·
Speaking of Stage3D – one of imortant things is batching geometry. So once you’ve got your vertices written to some storage (Vector or ByteArray) you need to concatenate those storages in a bigger one. And thats the time when ByteArray rocks. Take a look at a quick test: https://gist.github.com/2290228
#8 by jackson on April 3rd, 2012 ·
Batching is definitely very important to reducing draw calls as covered in my Stage3D Draw Calls series (part one, part two, part three). Upload speed is also important, as covered in my Stage3D Upload Speed Tester.
#9 by Paul on March 13th, 2013 ·
Thanks for your research – very helpful for large cryptographic operations. Just one thing worth mentioning – when copying data from a vector to a bytearray; by first defining the length of the destination bytearray before writing the vector to it (and using indexing instead of writeByte, as you mentioned), you cut the write speed almost in half.
#10 by Paul on March 14th, 2013 ·
I’ve been running benchmarks of my own and have found similar results. However, it’s probably worth mentioning that for all the speed advantages that Vector has over Bytearray for read/write operations (approx 2-6x faster), the opposite is true for reading/writing data *between* instances of these datatypes. Ie, copying data from one BA to another using BA.readBytes is about 5-10x faster than copying data from one Vector to another (using a loop, concat(), slice(), splice(), etc). So, if your code involves as many read/write operations as it does copy operations, the benefits of switching to Vectors is probably negligible (sadly).
#11 by jackson on March 14th, 2013 ·
That’s a good point. Some of those
Vector
functions cause memory allocations, even allocating whole newVector
objects. For more on this, see Hidden Object Allocations. I should probably do a formal test for copying between various collections:Vector
,ByteArray
,Array
,Dictionary
,Object
,BitmapData
, etc.#12 by Paul on March 16th, 2013 ·
Sounds great – I’d be very interested to see what you find out (or indeed, if you find a way to copy data between vectors as quickly as between bytearrays)
#13 by Kreative Place on May 29th, 2015 ·
Brilliant post