追加/组合ArrayBuffers的首选方法是什么?
我正在接收和解析具有各种数据结构的网络数据包。传入消息将读入ArrayBuffers。如果部分数据包到达,我需要存储它并在重新尝试解析它之前等待下一条消息。
目前我正在做这样的事情:
function appendBuffer( buffer1, buffer2 ) {
var tmp = new Uint8Array( buffer1.byteLength + buffer2.byteLength );
tmp.set( new Uint8Array( buffer1 ), 0 );
tmp.set( new Uint8Array( buffer2 ), buffer1.byteLength );
return tmp.buffer;
}
显然,由于ArrayBuffers具有固定长度,因此无法创建新缓冲区,但是是否需要初始化类型化数组?到达后我只想要能够将缓冲区视为缓冲区;类型和结构无关紧要。
答案 0 :(得分:7)
为什么不使用Blob? (我意识到当时可能还没有。)
只需使用您的数据创建一个Blob,例如var blob = new Blob([array1,array2,string,...])
,然后使用FileReader将其重新转换为ArrayBuffer(如果需要)(请参阅this)。
检查一下:What's the difference between BlobBuilder and the new Blob constructor? 这个:MDN Blob API
编辑:
我想比较这两种方法的效率(Blob和问题中使用的方法)并创建一个JSPerf:http://jsperf.com/appending-arraybuffers
似乎使用Blob的速度较慢(实际上,我猜这是使用Filereader来读取花费最多时间的Blob)。所以现在你知道;) 也许当有超过2个ArrayBuffer(比如从其块中重建文件)时,我会更有效率。
答案 1 :(得分:0)
您似乎已经得出结论,无法创建新的数组缓冲区。但是,出于性能考虑,将缓冲区的内容附加到标准数组对象,然后从中创建新的数组缓冲区或类型数组可能是有益的。
var data = [];
function receive_buffer(buffer) {
var i, len = data.length;
for(i = 0; i < buffer.length; i++)
data[len + i] = buffer[i];
if( buffer_stream_done())
callback( new Uint8Array(data));
}
大多数javascript引擎已经为动态分配的内存留出了一些空间。此方法将利用该空间而不是创建大量新内存分配,这可能是操作系统内核中的性能杀手。最重要的是,你还可以减少几个函数调用。
第二个更复杂的选择是预先分配内存。 如果您知道任何数据流的最大大小,那么您可以创建一个该大小的数组缓冲区,填充它(部分在必要时),然后在完成时将其清空。
最后,如果性能是您的主要目标,并且您知道最大数据包大小(而不是整个数据流),那么请从少数此大小的数组缓冲区开始。在填充预分配的内存时,在网络调用之间创建新的缓冲区 - 如果可能的话,异步创建。
答案 2 :(得分:-2)
您可以始终使用DataView
(http://www.khronos.org/registry/typedarray/specs/latest/#8)而不是特定的类型数组,但正如您对问题的评论中所提到的,您实际上无法使用{{1}独自一人。