bingo347
@bingo347
Crazy on performance...

Можно ли asm.js модулю подменить heap-buffer без перезапуска модуля?

Суть проблемы - необходимо организовать динамически выделяемую память для asm.js модуля
Как известно, в качестве виртуальной кучи он принимает ArrayBuffer размеры которого динамически менять нельзя
Адекватно подменить heap у работающего модуля способов не нашел
Пока просто дропаю экспорт, отдавая тем самым старый модуль на суд gc, копирую heap в буфер нужного размера и запускаю модуль с новым heap
Может есть способы лучше?
  • Вопрос задан
  • 173 просмотра
Решения вопроса 1
bingo347
@bingo347 Автор вопроса, куратор тега JavaScript
Crazy on performance...
Разобрался сам (ну и комменты от napa3um помогли), выложу тут, может пригодится кому

Сам ArrayBuffer пока в него ничего не записать память не ест
Но вот если в обычном js создать на его основе типизированный массив, то память съедается на размер буфера
Пример:
const heap = new ArrayBuffer(1 << 30); //создали буфер 1gb но память он пока не занимает
const heapUI16 = new Uint16Array(heap); // создали типизированный массив связанный с буфером
 // здесь будет сожрана память на весь буфер (1gb + доп данные от v8)
 // + будет большой такой лок процесса пока буфер забьется нулями, что плохо

Внутри asm.js типизированные массивы ведут себя совсем по другому, они просто связываются с буфером, но не заполняют его ничем и соответственно память не расходуется пока мы что-то куда-то не запишем.

Собственно решение:
Использовать в обычном js DataView для манипуляции heap извне, он так же не чем не заполняет буфер и память не ест
Пример:
const heap = new ArrayBuffer(1 << 30); //создали буфер 1gb
const heapView = new DataView(heap); //интерфейс для управления heap снаружи

//asm.js модуль
const asmModule = (function(std, env, heap) { 'use asm';
var HUI8 = new std.Uint8Array(heap); //это памяти пока не съест

//...
}({Uint8Array}, null, heap));

//функция для помещения строки на heap
function alocateString(pointer, str) {
  heapView.setUint32(pointer, str.length);
  for(let i = 0, p = pointer + 4; i < str.length; i++, (p += 2)) {
    heapView.setUint16(p, str.charCodeAt(i));
  }
}

//поместим не в начало буфера, а куда нить на позицию в 1мб длинную строку, 8кб:
alocateString(1024*1024, 'test'.repeat(1024));
Вуаля, после добавления в буфер 8kb расходуемая процессом память выросла так же на 8kb (ну с копейками)
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы