web-dev-qa-db-ja.com

ArrayBuffersの追加

ArrayBufferを追加/結合する好ましい方法は何ですか?

さまざまなデータ構造を持つネットワークパケットを受信して​​解析しています。着信メッセージは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は固定長なので、明らかに新しいバッファーを作成する必要はありませんが、型付き配列を初期化する必要がありますか?到着したら、バッファをバッファとして処理できるようにしたいだけです。タイプと構造は関係ありません。

29
user1421750

Blobを使用しないのはなぜですか? (当時は利用できなかったかもしれません)。

var blob = new Blob([array1,array2,string,...])などのデータを使用してBlobを作成し、FileReaderを使用して(必要に応じて)ArrayBufferに戻します( this を参照)。

これを確認してください: BlobBuilderと新しいBlobコンストラクタの違いは何ですか? そして、これ: MDN Blob API

EDIT:

私はこれら2つのメソッド(Blobと質問で使用されているメソッド)の効率を比較したいと思い、JSPerfを作成しました: http://jsperf.com/appending-arraybuffers

Blobの使用は遅いようです(実際、Filereaderを使用してBlobを読み取るのが最も時間がかかると思います)。だから、あなたは知っています;)多分それは、2つ以上のArrayBuffer(そのチャンクからファイルを再構築するような)がある場合に、より効率的になるでしょう。

7
Jb Drucker

新しい配列バッファーを作成する方法はないと結論付けたようです。ただし、パフォーマンスを向上させるために、標準の配列オブジェクトにバッファの内容を追加してから、そこから新しい配列バッファまたは型付き配列を作成することが有益な場合があります。

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番目の、より複雑なオプションは、事前にメモリを割り当てることです。データストリームの最大サイズがわかっている場合は、そのサイズの配列バッファーを作成し、それを(必要に応じて部分的に)埋め、完了したら空にします。

最後に、パフォーマンスが第一の目標であり、(ストリーム全体ではなく)最大パケットサイズがわかっている場合は、そのサイズの少数の配列バッファーから始めます。事前に割り当てられたメモリがいっぱいになったら、ネットワーク呼び出しの間に新しいバッファーを作成します(可能な場合は非同期に)。

1
Duco