webentwicklung-frage-antwort-db.com.de

ArrayBuffers anhängen

Was ist die bevorzugte Art, ArrayBuffers anzufügen/zu kombinieren?

Ich empfange und parse Netzwerkpakete mit verschiedenen Datenstrukturen. Eingehende Nachrichten werden in ArrayBuffers eingelesen. Wenn ein Teilpaket eintrifft, muss ich es speichern und auf die nächste Nachricht warten, bevor ich es erneut analysieren kann.

Momentan mache ich so etwas:

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;
}

Natürlich ist es nicht möglich, einen neuen Puffer zu erstellen, da ArrayBuffers eine feste Länge haben, aber müssen typisierte Arrays initialisiert werden? Bei der Ankunft möchte ich nur die Puffer als Puffer behandeln können; Typen und Strukturen sind nicht von Belang.

29
user1421750

Warum nicht einen Blob verwenden? (Mir ist klar, dass es zu dieser Zeit möglicherweise nicht verfügbar war).

Erstellen Sie einfach einen Blob mit Ihren Daten, z. B. var blob = new Blob([array1,array2,string,...]), und verwandeln Sie ihn (falls erforderlich) mithilfe eines FileReader in einen ArrayBuffer (siehe this ).

Überprüfen Sie dies: Was ist der Unterschied zwischen BlobBuilder und dem neuen Blob-Konstruktor? Und das: MDN Blob API

EDIT:

Ich wollte die Effizienz dieser beiden Methoden (Blobs und die in der Frage verwendete Methode) vergleichen und eine JSPerf erstellen: http://jsperf.com/appending-arraybuffers

Scheint, als wäre Blobs langsamer (in der Tat, ich denke, es ist die Verwendung von Filereader, um den Blob zu lesen, der die meiste Zeit in Anspruch nimmt). Jetzt wissen Sie es;) Vielleicht wäre es effizienter, wenn mehr als 2 ArrayBuffer vorhanden sind (wie das Rekonstruieren einer Datei aus ihren Chunks).

7
Jb Drucker

Es scheint, dass Sie bereits zu dem Schluss gekommen sind, dass es keinen Weg gibt, einen neuen Array-Puffer zu erstellen. Aus Performancegründen kann es jedoch vorteilhaft sein, den Inhalt des Puffers an ein Standard-Array-Objekt anzuhängen und dann einen neuen Array-Puffer oder ein typisiertes Array daraus zu erstellen.

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));
}

Die meisten Javascript-Engines haben bereits etwas Platz für dynamisch zugewiesenen Speicher. Bei dieser Methode wird dieser Speicherplatz verwendet, anstatt zahlreiche neue Speicherzuordnungen zu erstellen. Dies kann ein Leistungskiller innerhalb des Betriebssystemkerns sein. Darüber hinaus werden Sie einige Funktionsaufrufe abnehmen.

Eine zweite, umständlichere Option wäre die vorherige Zuweisung des Speichers. Wenn Sie die maximale Größe eines Datenstroms kennen, können Sie einen Array-Puffer dieser Größe erstellen. Füllen Sie ihn (ggf. teilweise) und leeren Sie ihn dann wenn es fertig ist. 

Wenn schließlich die Leistung Ihr Hauptziel ist und Sie die maximale Paketgröße (anstelle des gesamten Streams) kennen, beginnen Sie mit einer Handvoll Array-Puffer dieser Größe. Erstellen Sie beim Auffüllen des vorab zugewiesenen Speichers neue Puffer zwischen den Netzwerkaufrufen - wenn möglich asynchron. 

0
Duco