LINUX.ORG.RU

webassembly - пара теоретических вопросов.

 


1

2

Заранее прошу простить, но конкретный исходник по вопросу к посту подготовить не успеваю, но в конце пара ссылок на суть дела от других производителей…

Пытался сделать максимально компактную .wasm хрень на C с помощью emcc, задача которой просто байтики молотить - картинку обработать. Исходник оставил на другом компе, но дело не столько в нём, сколько в понимании модели памяти вебасма. Сделать-то компактно ополучилось: ноль инклудов, пара функций, пара глобальных переменных, экспорт всего наружу, всего 50 строк, ~400 байт на выходе.

Компилируется, в JS инициализируется, как надо не работает, но и не падает.

Вопросы:

  1. А правда, что wasm-инстанс (ну, «запущенная wasm программа») имеет модель памяти вида «плоский шмат» и любой указатель - это оффсет в этом шмате? То есть, если я хочу выделить память без планов её освобождать, я могу просто отступить куда-нибудь вперёд килобайт на 100 (при наличии Memory достаточного размера) и спокойно туда записывать? То есть, правда ли то, что в wasm-инстансе нет ничего подобного вызовам mmap/brk в линуксе, когда тебе могут надавать вообще разных адресов? В wasm у тебя только один шмат, просто можно как-то нарастить размер.

  2. А во что превратится глобальный static int[1024 * 1024]; написанный в сишном коде в webassembly? А можно я буду выделять себе свой единственно нужный буфер именно так? Пробовал взять на него указатель - дают некое число небольшое число типа 1050 - ну типа прямо как offset в пункте (1). Попробовал туда записывать - причём циклом по всему массиву - нормально, ничего не упало.

Пока вот два таких наводящих вопроса, конкретнее пока смысла нет, да и исходник провтыкал, найду запощу. Проблема просто в том, что я в память на webassembly пишу, а попытка посмотреть на тот же буфер со стороны JS выглядит так, что туда не пишется и там чисто - нолики лежат в той области, на которую пытаюсь смотреть. Может не туда смотрю, а может запись не происходит вообще. Странно, что в консоли хрома при этом ничего красного нет, ну вдруг я за границы массива пытался бы срать - так нет же.

Про исходник: в принципе все технические детали сп***ны отсюда: https://github.com/quin2/fast-paint

На что обратить внимание:

  1. Шмат памяти, в котором вся сишная часть этого проекта ковыряется, была «выделена» вот тут: https://github.com/quin2/fast-paint/blob/main/buffer.c#L63 - но, как мы знаем, в webassembly модель памяти - просто один шмат, поэтому этот malloc был скомпилён скорее всего в итоге во что-то, что вернуло uint32 с оффсетом на память.

  2. Далее со значением этого указателя screen имеют дело уже вот тут https://github.com/quin2/fast-paint/blob/main/script.js#L35 в виде обычного числа.

  3. Ну и основной цимес: как чуваки апдейтят canvas context: https://github.com/quin2/fast-paint/blob/main/script.js#L421 - вот просто хоба и скопировали прямо из буфера, в который инстанцировали webassembly с оффсетом pointer шмат памяти и закинули на ctx. Тащемта всё! В этой простоте и вся трагедия - попытка это повторить БЕЗ ВЫЗОВА malloc в сишной части, а просто отступив сколько-то памяти - это какой-то провал и непонятно почему, хоть и незаконно.



Последнее исправление: lesopilorama (всего исправлений: 10)
Ответ на: комментарий от madcore

Ну вот ты гуглил, а на вопросы ответить не смог. Зачем мне тогда гуглить, я же не пытаюсь оказаться в том же состоянии неможения.

lesopilorama
() автор топика
Последнее исправление: lesopilorama (всего исправлений: 1)

Пока что да, единственный memory на инстанс, который можно наращивать. Но в формате есть задел на возможность иметь несколько штук.

При старте инстанса memory можно заполнять изначальными данными из data объектов. Собственно static int[1024 * 1024] и скомпилируется как data объект и будет предзаполнять memory.

neumond
()
Ответ на: комментарий от neumond

Ну то есть static int[20000] приведёт к отрастанию mutable памяти инстанса на 20000*4 байт и этот кусок памяти можно будет считать «динамически выделенным в куче», при том что в .wasm бинаре его не будет?

lesopilorama
() автор топика
Ответ на: комментарий от lesopilorama

Поигрался с хелловорлдами.

static int lol[2000000] = {5};

Вот только так сильно прям вырос .wasm файл. Там ещё malloc из коробки прям работает. А с -s ALLOW_MEMORY_GROWTH=1 будет ещё вызывать автоматически memory.grow.

neumond
()

В общем, заработало. Смотрел не на ту память.

Вместо того, чтобы шариться по буферу, в который ты инстанцировал инстанс, надо шариться по памяти, которая лежит как exports.memory в самом инстансе.

lesopilorama
() автор топика