Может ли WebAssembly, скомпилированная с Emscripten, генерировать файлы меньшего размера
Я очень заинтересован в WebAssembly, но смущен тем, что даже пример "Hello World", написанный на C++ и скомпилированный с использованием Emscripten, выдает в общей сложности 396 КБ для загрузки в браузер. Что дает? Как это можно сделать более эффективным по размеру?
3 ответа
Резюме
- Для более крупных проектов, таких как игровой движок, код, сгенерированный Emscripten, имеет пропорционально меньшие накладные расходы по сравнению с небольшим примером Hello World.
- Emscripten недавно сделал большие улучшения в уменьшении размера кода. Убедитесь, что вы используете последнюю версию Emscripten.
- Добавление
-Os –closure 1
может уменьшить размер сгенерированного кода в 10 раз.
Ниже следует описание, чтобы ответить на вопрос how can this be made more size-efficient
Почему генерируется так много кода?
Количество создаваемой веб-сборки пропорционально количеству написанного кода на C++ и зависимостям этого кода. Программа на C++, зависящая от стандартной библиотеки, зависит от большего количества кода, чем вы могли ожидать. Просто add()
функционировать так...
int add(int x, int y) {
return x + y;
}
..Сформируем короткую функцию веб-сборки, например:
(func $add (param $x i32 $y i32) (return i32)
(get_local 0
get_local 1
i32.add))
Но призыв к printf
нужно будет иметь определения для таких функций, как strlen
, flockfile
, funlockfile
, memcpy
, fwrite
, fputs
, __stdio_write
т.е. все функции из стандартной библиотеки, необходимые для создания printf
вызов. Программа на C++, работающая в собственной среде, будет просто привязана к соответствующему libc для платформы, но Webassembly должна нести эти библиотечные зависимости.
В дополнение к зависимостям библиотеки пользовательского пространства, инструмент, который генерирует Webassembly, также должен предоставлять среду выполнения, которая обрабатывает системные вызовы. Таким образом, программа Hello World должна иметь определения, которые переопределяют системные вызовы для выделения памяти и для записи байтов.
Как компилятор может уменьшить размер кода?
Алон Закай, создатель и сопровождающий emscripten, написал в Emscripten статью Mozilla Hacks " Сокращение размеров веб-сборок и Javascript". Я собираюсь обобщить основные моменты из этой статьи здесь:
Первоначально Emscripten фокусировался на упрощении портирования существующих программ на C и C++, предоставляя среду Posix путем реализации libc и среды выполнения для системных вызовов. Во имя удобства часто включалось больше кода, чем требовалось.
Большая часть времени выполнения была реализована в виде кода Javascript. Emscripten генерирует код, который перезванивает между кодом веб-сборки приложения / библиотеки и средой выполнения Javascript.
Код, который никогда не вызывается, должен быть удален. В компиляторах это обрабатывается оптимизацией под названием Dead Code Elmination. Emscripten строит график всех функций и удаляет те части, которые никогда не вызываются из main. Хорошо, это не совсем правильно, но достаточно для этого объяснения.
Но компилятор ранее не был способен генерировать такой граф для вызовов, которые пересекали границу между Webassembly и Javascript. Это изменилось с включением инструмента wasm-dce. Теперь Emscripten может создавать график как веб-сборки, так и кода Javascript.
Каков предел "усадки" для программы Hello World?
printf
это общая функция, которая работает с файловыми дескрипторами и является поточно-ориентированной. Код, сгенерированный для вызова printf, почти все должен быть там.
Если вы хотите больше экспериментировать с генерируемым кодом, я рекомендую интерактивную среду разработки http://webassembly.studio/. В нем приведен пример проекта Hello World с README, в котором описывается, какой код библиотеки и код Javascript исполняется.
Более высокие уровни оптимизации вводят все более агрессивную оптимизацию, что приводит к повышению производительности и размера кода за счет увеличения времени компиляции. - Источник
Вот что говорят документы emscripten об уменьшении размеров файлов. Помните о том, что более высокий уровень оптимизации не означает меньший размер файла. Каждый вариант оптимизации ведет себя по-разному, что довольно хорошо описано в документации.
В следующем примере используется -Os
Опция оптимизации кода, которая заставляет компилятор вести себя так:
Как -O3, но с дополнительными оптимизациями, которые уменьшают размер кода за счет производительности. Это может повлиять как на генерацию битового кода, так и на JavaScript. - Источник
emcc -Os file.cpp
Вы получите меньшие размеры и лучшую производительность, когда wasm реализует API-интерфейсы DOM/web, поэтому вам потребуется обратный вызов javascript .