Использование памяти объектов ArrayBuffer и Blob-объектов

#javascript #blob #arraybuffer

#javascript #большой двоичный объект #arraybuffer

Вопрос:

Я получаю фрагменты данных ArrayBuffer и добавляю каждый фрагмент в массив на a web worker , и когда я получаю все фрагменты, я преобразую этот массив фрагментов в большой двоичный объект.

 //worker.js

const array = []

this.onmessage = function(e){
     if(e.data.done)
     {
        const blob = new Blob(array);
        this.postMessage(blob)
        shunks.length = 0
     }
     else
     {
         array.push(e.data.chunk)
     }
}
 

МОИ ВОПРОСЫ

  1. если размер массива достигает 2 ГБ, он будет сохранен в памяти, верно? это означает, что я не смогу заполнить этот массив данными, превышающими мою доступную память?
  2. Когда я создам большой двоичный объект из этого массива, займет ли большой двоичный объект еще 2 ГБ из памяти?

Комментарии:

1. Да, он всегда находится в памяти, по крайней мере, до тех пор, пока на него есть ссылка. Да, это ограничено доступной памятью. Да, большой двоичный объект займет больше памяти, чем память, уже занятая исходными ArrayBuffer объектами

Ответ №1:

Это зависит от обстоятельств…

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

Однако браузеры могут использовать здесь некоторые оптимизации, например, IIRC Chrome сохраняет свои двоичные объекты на диске пользователя вместо того, чтобы раздувать память, и я полагаю, что они могли бы использовать аналогичные приемы для ArrayBuffers.

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

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

Комментарии:

1. спасибо за хорошее объяснение, но возможно ли создать большой двоичный объект для каждого фрагмента и объединить все эти созданные большие двоичные объекты в конце в один? Я не упоминал, что буфер массива является файлом, и я использовал большие двоичные объекты, чтобы сгенерировать URL-адрес объекта URL.createObjectURL(blob) , чтобы иметь возможность загрузить фактический файл. Есть ли какой-нибудь способ сохранить каждый фрагмент буфера непосредственно на диск в том же файле без использования больших двоичных объектов, что-то похожее на файловую систему узла fs require('fs').writeFileSync('/path', Buffer.from(buffer)) , но здесь нам нужно из полного буфера, а не из фрагментов @Kaiido

2. Да, вы можете сделать new Blob([blob1, blob2, blob3]) , и в этом случае новые данные не создаются.

3. Я просто хочу сообщить вам, что, как вы предложили, API доступа к файловой системе является идеальным решением для этого случая. Мне даже не нужно было работать с большими двоичными объектами, просто сохраняя буферы непосредственно на свой диск. Я публикую код, как я это сделал. Спасибо.