Четверг, 21.11.2024, 09:27
WebAssembly
Главная | Блог | Регистрация | Вход
Меню сайта
Наш опрос
Оцените мой сайт
Всего ответов: 0
Мини-чат
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

21:03
WebAssembly тяжелее ассемблера

Ура, свершилось? Прямой доступ к машинным кодам прямо из браузера?

Нет, не совсем так. Простые компилируемые в машинные коды программы на таких языках, как Ada и Delphi, всё ещё остаются шустрее. И вот, почему.

Память

Память WebAssembly, — это массив байт ограниченного размера с возможностью роста, плюс набор переменных модулей, вклад которых незначителен. Память настоящей программы, — это виртуальная память большого размера, например, 2Гб.

Сегменты данных

Чтобы загрузить модуль WebAssembly со встроенным блоком памяти, надо скопировать все байты в массив памяти WebAssembly. Если открыть несколько вкладок одного сайта, в каждой вкладке загрузится своя копия всех блоков памяти WebAssembly (если только не прибегать к ухищрениям с opener, тянущим на кандидатскую). Чтоб загрузить исполняемый или динамический модуль обычной программы, надо спроецировать страницы памяти с диска в виртуальную память. Пока страницы памяти не потребуются, их можно даже не грузить. Можно прочитать в оперативную память и разделить между всеми экземплярами программы. Или между всеми программами, загрузившими одну и ту же динамическую библиотеку. Можно спроецировать страницы памяти в режиме только для чтения, для констант, и тогда такие страницы точно общие. Можно спроецировать страницы памяти в режиме копирования при записи. Пока ничего не изменилось, страницы памяти общие для нескольких программ. Для WebAssembly эти прелести виртуальной памяти недоступны.

Стеки

Модулям WebAssembly доступен неадресуемый стек, который может быть достаточно просторным, и часто приходится выделять искусственный стек в памяти WebAssembly. Вся выделенная память WebAssembly является настоящей, то есть, дорогой. Обычные программы выделяют не память, а виртуальные адреса для стека, и уже потом в этих адресах постранично выделяется память по мере необходимости. Виртуальное адресное пространство позволяет удобно зарезервировать большое пространство адресов для стека, а всё оно может так и не понадобиться, и страницы выделены для него не будут.

Исполняемый код

Модули WebAssembly на самом деле не в машинных кодах, а чтобы их перевести, требуется время при каждой загрузке. Время можно экономить, если положиться на кеширование машинных кодов, но для этого нужно загружать чётко определённым образом, и уже не все возможности WebAssembly легко доступны.

Обычные программы уже в машинных кодах, и их код проецируется страницами в виртуальную память.

Косвенные вызовы

Обычной программе почти ничего не стоит ссылаться на любые свои байты, в том числе на адреса функций. В WebAssembly каждая функция, которую можно вызвать косвенно, занимает место в массиве косвенно вызываемых функций. И, например, при загрузке динамической библиотеки требуется копировать новые функции в общий массив. Чем их больше, тем дольше обработка.

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

В некоторых компиляторах для простоты индексы общие. То есть, массивов много, но в большинстве массивов заглушка с ошибкой, и только в тех ячейках, где совпадение сигнатуры, настоящая ссылка на косвенно вызываемую функцию. Но тогда нужно обслуживать несколько преимущественно пустых массивов. Либо можно все массивы компактифицировать, но тогда весьма усложняются релокации.

Релокации

Релокация, — это загрузка модуля, обычно динамической библиотеки, по её «не основному» базовому адресу. У обычной программы это хорошо поддержанная операция. Надо производить смещение всего лишь по одному базовому адресу, ведь код и данные двигаются синхронно. В некоторых операционных системах имеется система кеширования перебазированных библиотек, так что их можно подгружать, проецируя страницы с диска.

В WebAssembly релокации производятся как минимум по двум «адресам». Это собственно адрес сегмента данных в памяти WebAssembly, и также начальный индекс косвенно вызываемых функций. А если применяется компактное выделение массивов функций разной сигнатуры, то сколько сигнатур, столько и дополнительных базовых адресов релокаций.

Многопоточность

Обычные программы достаточно непринуждённо могут запускать несколько потоков. Программы на WebAssembly для подлинной многопоточности должны использовать такой инструмент, как Worker, и передать экземплярам массив Wasm.Memory, созданный с флагом shared: true. Использование этого флага требует ограничить сверху максимально доступную память, чего не происходит в обычных программах.

Также начинаются довольно весёлые проблемы с динамической загрузкой библиотек. Разные Worker друг от друга изолированы. Да, они могут обменяться сообщениями между собой и с Window, чтобы обрести общую Wasm.Memory, но программа на этом не заканчивается. Кроме данных ещё нужен исполняемый код, а он у каждого Worker свой. Чтобы создать иллюзию обычной многопоточной программы, нужно в каждом Worker одинаковым образом грузить все модули, и чтобы у них у всех было одинаковое видение всех релокаций.

Гипотетически модули могут быть заменены на сервере прямо в тот момент, когда Worker их пытается грузить, и у Worker загрузится своя версия модуля. Чтобы с этим бороться, можно сами загруженные WebAssembly сохранять как Blob и передавать в Worker, чтобы точно загрузилось то, что нужно. Но такие усложнения часто ведут к тому, что ломается стандартное кеширование исполняемого кода. Куда ни кинь, всюду клин.

Итог

Компилировать обычные программы по-прежнему имеет смысл. Разрыв между обычными программами и WebAssembly по использованию ресурсов велик, и трудно представить, чтобы он был сокращён. Архитектуру WebAssembly ещё требуется радикально поменять, и всё равно она останется далеко позади.

Из-за сложностей поддержки динамических библиотек компиляторы часто создают замкнутые на себя статические модули, не раскрывающие потенциал ни обычных разделяемых библиотек, ни даже WebAssembly.

Тем не менее, поддержка WebAssembly имеет важный смысл. Чем меньше кликов, тем выше конверсия. WebAssembly нужен для «малокликабельных» версий программы. Для того, чтобы заманить скачать полноценную быструю версию программы.

У JavaScript-«программ» преимущества устанавливаемых версий просматриваются с большим трудом. Программы для WebAssembly можно так переносимо писать, что у них будут быстрые родные версии, не требующие встроенного браузера.

Просмотров: 160 | Добавил: OCTAGRAM | Теги: WebAssembly, shared object, dll | Рейтинг: 0.0/0
Всего комментариев: 0
avatar
Вход на сайт
Поиск
Поделиться
Календарь
«  Март 2024  »
ПнВтСрЧтПтСбВс
    123
45678910
11121314151617
18192021222324
25262728293031
Архив записей
Файлы
[15.07.2024][Документация]
C Intermediate Language: учебник и руководство (0)
[28.05.2024][Философия IT]
Джоэл Спольски о программировании (0)
[25.03.2024][История IT]
Hard drive: Bill Gates and the making of the Microsoft empire (0)
Полезные ссылки