附加ArrayBuffers

时间:2012-05-28 14:16:53

标签: javascript arraybuffer typed-arrays

追加/组合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具有固定长度,因此无法创建新缓冲区,但是是否需要初始化类型化数组?到达后我只想要能够将缓冲区视为缓冲区;类型和结构无关紧要。

3 个答案:

答案 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)

您可以始终使用DataViewhttp://www.khronos.org/registry/typedarray/specs/latest/#8)而不是特定的类型数组,但正如您对问题的评论中所提到的,您实际上无法使用{{1}独自一人。