Подтвердить что ты не робот

Добавление ArrayBuffers

Каков предпочтительный способ добавления/объединения 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 имеют фиксированную длину, но необходимо ли инициализировать типизированные массивы? По прибытии я просто хочу, чтобы иметь возможность обрабатывать буферы в качестве буферов; типы и структуры не имеют никакого отношения.

4b9b3361

Ответ 1

Вы всегда можете использовать DataView (http://www.khronos.org/registry/typedarray/specs/latest/#8), а не определенный типизированный массив, но, как уже упоминалось в комментариях к ваш вопрос, вы действительно не можете сделать многое с ArrayBuffer самостоятельно.

Ответ 2

Почему бы не использовать Blob? (Я понимаю, что он мог быть недоступен в то время).

Просто создайте Blob с вашими данными, например var blob = new Blob([array1,array2,string,...]), и верните его в ArrayBuffer (если необходимо) с помощью FileReader (см. this).

Проверьте это: В чем разница между BlobBuilder и новым конструктором Blob? И это: API MDN Blob

EDIT:

Я хотел сравнить эффективность этих двух методов (Blobs и метод, используемые в вопросе) и создал JSPerf: http://jsperf.com/appending-arraybuffers

Кажется, что использование Blobs медленнее (на самом деле, я думаю, это использование Filereader для чтения Blob, который занимает больше всего времени). Итак, теперь вы знаете;) Может быть, это было бы более эффективно, когда было больше 2 ArrayBuffer (например, восстановление файла из его кусков).

Ответ 3

Кажется, вы уже пришли к выводу, что нет никакого способа создать новый буфер массива. Однако для производительности было бы полезно добавить содержимое буфера в стандартный объект массива, а затем создать новый массив или массив из этого массива.

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 уже будет выделено пространство для динамически распределенной памяти. Этот метод будет использовать это пространство вместо создания множества новых распределений памяти, которые могут быть убийцами производительности внутри ядра операционной системы. Кроме того, вы также сбриваете несколько вызовов функций.

Вторым, более привлекательным вариантом будет выделение памяти заранее. Если вы знаете максимальный размер любого потока данных, тогда вы можете создать буфер массива такого размера, заполнить его (частично, если необходимо), а затем удалить его, когда это будет сделано.

Наконец, если ваша основная цель - производительность, и вы знаете максимальный размер пакета (вместо всего потока), тогда начинайте с нескольких массивов буферов такого размера. Когда вы заполняете свою предварительно выделенную память, создавайте новые буферы между сетевыми вызовами - асинхронно, если это возможно.