web-dev-qa-db-fra.com

Ajouter des ArrayBuffers

Quelle est la meilleure façon d’ajouter/combiner ArrayBuffers?

Je reçois et analyse des paquets réseau avec diverses structures de données. Les messages entrants sont lus dans ArrayBuffers. Si un paquet partiel arrive, je dois le stocker et attendre le message suivant avant de tenter de le réanalyser.

Actuellement, je fais quelque chose comme ça:

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

Évidemment, vous ne pouvez pas vous passer de la création d'un nouveau tampon car les ArrayBuffers ont une longueur fixe, mais est-il nécessaire d'initialiser des tableaux typés? À mon arrivée, je souhaite simplement pouvoir traiter les tampons comme des tampons; types et structures ne sont pas préoccupants.

29
user1421750

Pourquoi ne pas utiliser un blob? (Je me rends compte qu'il n'était peut-être pas disponible à ce moment-là).

Créez simplement un Blob avec vos données, comme var blob = new Blob([array1,array2,string,...]), et reconvertissez-le en un ArrayBuffer (si nécessaire) en utilisant un FileReader (voir this ).

Vérifiez ceci: Quelle est la différence entre BlobBuilder et le nouveau constructeur Blob? Et ceci: API MDN Blob

MODIFIER :

Je voulais comparer l'efficacité de ces deux méthodes (Blobs et la méthode utilisée dans la question) et créer un JSPerf: http://jsperf.com/appending-arraybuffers

On dirait que l'utilisation de Blobs est plus lente (en fait, je suppose que c'est l'utilisation de Filereader pour lire le Blob qui prend le plus de temps). Alors maintenant, vous savez;) Peut-être que ce serait plus efficace quand il y a plus de 2 ArrayBuffer (comme reconstruire un fichier à partir de ses morceaux).

7
Jb Drucker

Vous semblez déjà avoir conclu qu'il n'y avait aucun moyen de créer un nouveau tampon de tableau. Toutefois, pour des raisons de performances, il peut être avantageux d’ajouter le contenu du tampon à un objet tableau standard, puis de créer un nouveau tampon tableau ou un tableau typé à partir de cet objet.

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

La plupart des moteurs javascript auront déjà un espace réservé pour la mémoire allouée dynamiquement. Cette méthode utilisera cet espace au lieu de créer de nombreuses nouvelles allocations de mémoire, ce qui peut nuire aux performances dans le noyau du système d'exploitation. En plus de cela, vous réduirez également quelques appels de fonction.

Une deuxième option, plus complexe, serait d’allouer la mémoire au préalable . Si vous connaissez la taille maximale d’un flux de données, vous pouvez créer un tampon de tableau de cette taille, le remplir (partiellement si nécessaire), puis le vider terminé. 

Enfin, si les performances sont votre objectif principal et que vous connaissez la taille de paquet maximale (au lieu de l’ensemble du flux), commencez avec une poignée de mémoires tampon de tableau de cette taille. Lorsque vous remplissez la mémoire préallouée, créez de nouveaux tampons entre les appels réseau, de manière asynchrone si possible. 

0
Duco