WebAssembly — всё по этой теме для программистов


Оглавление (нажмите, чтобы открыть):

Что такое WebAssembly: революционная технология для веба и не только

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

Начать стоит с важного замечания. Заявления о высокой скорости и производительности WebAssembly (Wasm) или другой технологии не нужно воспринимать буквально. В них обычно идет речь об относительной скорости и производительности, то есть о скорости wasm по сравнению с чем-то. Держите это в уме.

WebAssembly — безопасный и эффективный низкоуровневый бинарный формат для веба. Давайте рассмотрим, что это значит.

Эффективность

Когда кто-то говорит о Wasm, как правило речь идёт о его потенциальной высокой производительности. Объясняют высокую производительность тем, что браузер компилирует Wasm в эффективный машинный код. Однако высокая производительность — не единственное объяснение эффективности WebAssembly.

Wasm изначально проектировался с учётом формата компактных бинарных файлов. Поэтому его можно быстро загружать. Но, что более важно, код Wasm может быть преобразован в машинный прямо во время загрузки. Это называется потоковой компиляцией.

До появления WebAssembly код, написанный на C++ или Rust, перед использованием в вебе приходилось компилировать в JavaScript. Современные виртуальные машины компилируют JavaScript в машинный код, но начать этот процесс, по сути, можно только тогда, когда весь JS-код будет загружен. WebAssembly, напротив, компилируется в машинный код по мере загрузки, что сильно влияет на скорость запуска кода на исполнение. Настолько сильно, что узким местом уже становится скорость загрузки данных по сети, особенно на мобильных устройствах.

Потоковая компиляция — это прекрасно. Но и здесь есть нюансы. Так что сама возможность компилирования кода в Wasm не всегда означает, что это непременно нужно делать. Не так уж и сложно написать такой JS-код, который будет компактнее по размеру, чем порция компилированного в Wasm кода на C++. Ведь коду на JS не нужно нести с собой машинерию для управления памятью или любые другие функции, предоставляемые самим браузером. То есть вам не придётся реализовывать Array или библиотеку для парсинга JSON . Эти возможности уже есть в среде исполнения JavaScript — в браузере.

Wasm, напротив, не имеет никакого особого представления о C++ (или любом другом языке). Поэтому среда исполнения Wasm не предоставляет стандартную библиотеку C++ и компилятору её приходится добавлять в каждый бинарный файл. Как минимум, должны быть включены используемые в коде части библиотеки.

Увы, такие подробности способны смутить иного читателя. Причина тому — необходимость понимания того, как на самом деле работают и JS, и C++ и насколько они разные. Но не отчаивайтесь! Вы можете не понимать всех тонкостей, и тем не менее применять Wasm с пользой.

Безопасность

Развитие Web напрямую влияет на эволюцию браузеров. Браузеры постоянно наращивают свои возможности, всегда при этом оставаясь гарантами безопасности от злонамеренных действий со стороны. WebAssembly также следует по этому пути.

Wasm выполняется в песочнице, как и JavaScript. Он не имеет доступа к операционной системе, но имеет доступ к тем же API, что и JS. Поэтому WebAssembly не может выполнять произвольные системные вызовы или читать внутреннюю память браузера. Чтобы получить доступ к файловой системе, Wasm должен использовать File API, как JavaScript.

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

WebAssembly обеспечивает дополнительную безопасность для таких языков, как C и C++. Классический пример — переполнение буфера, которое используется для внедрения вредоносного кода. Сами принципы работы WebAssembly делают невозможным появление этого класса уязвимостей. Вы можете переполнить буфер, C++ даёт такую возможность. Но внедрить вредоносный код не получится из-за отсутствия исполняемой памяти.

Однако, не стоит думать, что WebAssembly защищает от любых классов уязвимостей. Злоумышленник не сможет произвести атаку с инъекцией кода напрямую, однако у него остаётся возможность перехватить управление потоком исполнения через атаку повторного использования кода (code reuse attack) с помощью непрямых вызовов (indirect calls). Например, переполнение буфера способно вызвать перезапись указателя на функцию, да так, что указатель станет ссылаться на другую функцию. Упомянутые атаки против кода на C++ возможны благодаря самой природе языка. Использование языков вроде Rust позволяет избежать многих уязвимостей, но не всех. Да и для JavaScript существуют свои атаки подобного рода. Они есть и в других языках программирования, включая JavaScript.

Низкоуровневый бинарный формат

WebAssembly создавался в первую очередь как цель для компиляции, а не как язык, на котором будут писать вручную, хоть это и возможно. В основном вы будете писать код на более человекочитаемых языках, вроде C++ и Rust, и лишь затем компилировать ваш код в код машиночитаемый, который ещё называют «байт-кодом» (bytecode).

Пример кода C/C++, скомпилированного в байт-код

Байт-код похож на нативный машинный код, который использует ваш компьютер. Однако байт-код создан для виртуальной, а не реальной машины. Это делает код достаточно низкоуровневым, чтобы можно было производить оптимизации, но всё ещё портируемом, что позволяет не думать об архитектуре процессора (x64, ARM, и т.п.) на стороне конечного пользователя. Веб-браузеры имеют встроенные виртуальные машины для выполнения WebAssembly. Но вот ведь в чём штука: WebAssembly применим не только для Web. Об этом ниже.

Возможно, вы знакомы с другими форматами байт-кода, например, .Net CIL (CLR) или Java Bytecode (JVM). Вы могли бы подумать, почему разработчики не встроили в браузер один из этих (или других подобных) вариантов. Чтобы объяснить причину, придётся углубиться в технические нюансы, но здесь обойдёмся без этого. Достаточно понимать, что разные виртуальные машины имеют разные и часто несовместимые цели. Например, файлы Wasm могут быть верифицированы и скомпилированы виртуальной машиной на лету, что обеспечивает возможность потоковой компиляции. Другие форматы байт-кода не всегда обеспечивают такую возможность.

Существует множество других причин. Но даже если разработчики браузеров обеспечили бы поддержку одного из форматов байт-кода, вы не смогли бы исполнять существующие бинарные файлы как есть, так как в данном случае не соблюдается принцип безопасности: изоляция кода от операционной системы. Например, JVM имеет неограниченный доступ к файловой системе с помощью API типа java.io — запретной для веба технологии. Вместо этого разработчики WebAssembly выбрали путь исполнения в песочнице и использования существующих Web API.

WebAssembly уничтожит JavaScript?

Нет, JavaScript никуда не денется. Этот язык создан для того, чтобы на нём писали люди. Wasm создан для того, чтобы в него компилировался код, написанный людьми на C++, Rust и так далее. Фактически, по причине молодости WebAssembly на данный момент во многих случаях JavaScript всё ещё остаётся лучшим выбором для решения задач, связанных с веб. И при всех своих недостатках современный JS — отличный язык программирования.

Но никто не может предсказать будущее. WebAssembly не предназначен для того, чтобы уничтожить JavaScript. Но нельзя исключить, что в будущем какой-то язык программирования сможет конкурировать с JS в вебе благодаря компиляции в Wasm. Если это случится, скорее всего речь будет идти о новом языке типа Dart, Elm, Reason, созданном для веба.

Придётся ли компилировать JavaScript в Wasm?

JavaScript — предельно динамический язык. Только взгляните на этот забавный пример.

Если вы захотите скомпилировать произвольный JS-код в WebAssembly, например, библиотеку Lodash, вам придётся поставлять вместе с кодом ещё и солидную часть среды исполнения JavaScript. А чтобы достичь и той производительности, которая присуща браузерной реализации JS, вам придётся вместе с кодом поставлять среду исполнения практически целиком. Это непрактично из-за слишком большого размера файлов.

Поэтому компиляция JavaScript в Wasm в целом не очень хорошая идея. Но жёстко ограниченно подмножество JavaScript или аналогичный диалект могут быть быстрыми.

Например, Facebook использует оптимизатор JavaScript — Prepack. В целом этот проект не связан с Wasm. Но разработчики оптимизатора ищут способы безопасной статической компиляции некоторых паттернов кода JavaScript в WebAssembly. Пока неясно, насколько перспективны эти эксперименты.

Ещё один вариант — написание кода на языке, который похож на JavaScript, но не является им. AssemblyScript похож на TypeScript. Знакомые с JavaScript программисты могут использовать его, чтобы переписать критически важные для производительности компоненты JS-приложения.

AssemblyScript — многообещающая технология. Но она пока не подходит для создания приложений от начала до конца. Большая часть ограничений AssemblyScript связана с будущими возможностями Wasm. Важно не путать AssemblyScript с TypeScript. TypeScript представляет собой надмножество JavaScript, поэтому вся функциональность JS доступна в TS.

WebAssembly 1.0 aka MVP

Главный барьер для стремительного роста популярности Wasm — поэтапная разработка этой технологии. Из-за неё не все возможности WebAssembly можно широко применять. Версия 1.0, которую также назвали MVP, лучше всего подходит для языков типа C/C++ и Rust, но не всегда хорошо работает даже с ними.

Это правильное намеренное решение, так как стандарты языков и технологий постоянно совершенствуются. Разработчики получают обратную связь и принимают решения на её основе. Это позволяет избежать выпуска откровенно неудачных решений, которые потом практически невозможно изъять из обращения.

В будущем Wasm будет поддерживать высокоуровневые языки, например, Java и OCaml. Даже Dart, Elm и Reason когда-то будут компилироваться в WebAssembly. Одним из «отсутствующих кусочков» всё ещё является сборщик мусора (garbage collection, GC). GC работает в Wasm, но пока не очень эффективно.

Также проблемой остаётся прямой доступ к API DOM/HTML. Сейчас WebAssembly должен делать вызов с помощью JS, когда необходимо обратиться к WEB API. Wasm не может напрямую обрабатывать сгенерированные WEB API объекты. Поэтому инструментам вроде Emscripten и wasm-bindgen приходится делать дополнительную работу, чтобы скрыть этот факт от вас.

Как работать с WebAssembly

Здесь начинаются странности. Как вы помните, код компилируется в Wasm, вы не пишете его на WebAssembly вручную. Поэтому подходы к работе зависят от языка, на котором вы пишете и который собираетесь компилировать в Wasm.

Если вы пишете на C/C++, используйте Emscripten. Он оборачивает Clang/LLVM и выдаёт JavaScript-код, который может взаимодействовать с WEB API.

Если вы пишете на Rust, вам повезло. Разработчики ядра Rust активно работают над совместимостью с WebAssembly. Подробности можно узнать из книги Rust and WebAssembly.

Есть и другие языки, которые работают над поддержкой Wasm, например, Go.

Не Web, да и не ассемблер

В этой публикации речь идёт преимущественно об использовании WebAssembly в браузере. Стоит отметить, что название технологии вводит в заблуждение. Wasm — не ассемблер, это текстовое представление бинарного байт-кода.

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

Что ещё важнее, WebAssembly не предназначен исключительно для веба. В настоящее время использование Wasm вне браузеров набирает обороты. Ниже несколько конкретных примеров.

  • Nebulet. Микроядро операционной системы для запуска Wasm.
  • wasmjit, виртуальная машина WebAssembly.
  • Wasmer. Универсальная среда исполнения Wasm.
  • Воркеры Cloudflare для запуска Wasm.
  • Fastly Terrarium, среда для развёртывания Wasm.
  • Ewasm. Виртуальная машина WebAssembly.
  • Pariti wasmi, интерпретатор Wasm.

Заключение

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

Адаптированный перевод публикации WebAssembly: Neither Web, Nor Assembly, but Revolutionary by Allen Conway. Мнение автора оригинальной публикации может не совпадать с мнением администрации «Хекслета».

Сможет ли WASM потеснить JavaScript и изменить будущее веб-разработки

Дата публикации: 2020-07-18

От автора: этот вопрос на устах у многих разработчиков с тех пор, как WebAssembly (WASM) начал выглядеть так, как будто это может стать реальностью. Хотя многие предположили, что грядет замена JavaScript WASM, те, кто участвует в создании последнего, отрицают такое намерение.

В официальном FAQ на webassembly.org этот вопрос значится одним из первых — и ответ на него: «WebAssembly предназначен для дополнения, а не для замены JavaScript». Эксперты, такие как Брендон Эйх, бывший генеральный директор Mozilla, предсказывают будущее, в котором WebAssembly и JavaScript будут совместно развиваться.

Будущее веб-разработки

Хотя он может и не уничтожать JavaScript, WebAssembly, безусловно, изменит лицо front-end веб-разработки. Пока еще слишком рано говорить о том, как все изменится, но мы уже достаточно далеко продвинулись, чтобы делать некоторые прогнозы о будущем веб-разработки. Включение WebAssembly в будущее веб-разработки это:

Чрезвычайно высокая скорость

Как создать сайт самому?

Какие технологии и знания необходимы сегодня, чтобы создавать сайты самостоятельно? Узнайте на интенсиве!

WebAssembly делает возможным лингвистическое разнообразие

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

Уже существует впечатляющий список реализаций, с компиляцией WASM, поддерживаемой на более чем 20 разных языках, включая:

Как создать сайт самому?

Какие технологии и знания необходимы сегодня, чтобы создавать сайты самостоятельно? Узнайте на интенсиве!

Такая диверсификация языков позволит развить веб-фреймворки для разработчиков этих языков, что в свою очередь даст им возможность разрабатывать приложения непосредственно на выбранных ними языках.

Некоторыми ранними примерами являются Yew для Rust и Humble в Go (Humble в настоящее время позиционирует GopherJS как «компиляцию на javascript», но я ожидаю, что скоро будет поддерживаться WASM back-end)

WebAssembly делает возможным создавать чрезвычайно быстрые веб-приложения

WASM позволит добиться довольно впечатляющего повышения производительности. Мы видели, как Firefox продемонстрировал, что в отличие от JavaScript, WASM может быть скомпилирован и выполнен так быстро, как это можно сделать в локальной сети.

Это улучшение времени парсинга устраняет одно из самых узких мест современных веб-приложенияй на JavaScript: время начальной загрузки. В наборе тестов, опубликованных Figma, средство проектирования на основе браузера при реализациях, использующих WebAssembly, показало 3-кратное уменьшение времени загрузки по сравнению с asm.js реализациями. Для больших документов это означало вместо более чем 10 секунд до первого взаимодействия всего менее чем 5. Это потрясающее улучшение.

Улучшение производительности во время выполнения было менее впечатляющим, но все же ощутимым. Контрольные показатели интенсивных графических операций для WASM по сравнению с D3 показали 30% улучшение у крупных проектов.

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

Уже есть доказательства того, что разработчики фреймворков исследуют эти возможности, а Ember.js рассматривает реализацию WASM для Glimmer VM. Я думаю, что эта тенденция будет развиваться все активнее. Представьте, что JavaScript-фреймворки отправляют «стартовые» последовательности, скомпилированные в WASM, которые постепенно расширяются с помощью JavaScript и загружают ваше приложение на основе JavaScript, позволяя сложным веб-приложениям загружаться и достигать первого взаимодействия так же быстро, как и простые статические веб-сайты.

WebAssembly сделает возможным параллелизм

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

В недавней презентации о будущем браузера Лин Кларк из Mozilla подчеркнул, что та часть веб-опыта, которую браузеры не могут «невидимо» параллелизировать, это фактический код приложения. JavaScript был разработан как однопоточный язык, а в то время как более новые инструменты, такие как Web Workers, допускают некоторый параллелизм в JavaScript, им все же сложно работать только на относительно ограниченном уровне курса.

Такие языки, как Rust и Go, были разработаны с учетом параллелизма с самого начала, что значительно облегчает написание параллельных приложений. Функция потоков WebAssembly по-прежнему остается лишь предложением, но как только она станет реальностью, мы сможем увидеть веб-приложения, использующие параллелизм на низком уровне.

В большей степени это опять же будет связано с уровнем фреймворков и библиотек. Я не предполагаю, что средний разработчик приложений использует потоки WebAssembly в своем приложении, но в рамках платформы существует огромный потенциал. Новая Fiber Architecture от React уже рассматривает возможность разделения внутренних процессов рендеринга, которые можно передавать и откладывать. Представьте, что Fibre на базе WebAssembly разбивает процессы рендеринга для всех доступных ядер, а затем просто передает их в приложение JavaScript по мере необходимости.

Яркое будущее веб-разработки

Не знаю, как вы, но я очень взволнован возможностями, предоставляемыми WebAssembly, даже если я никогда не буду иметь с ними дело напрямую и не буду кодировать на JavaScript. По мере того, как инструментарий продолжает развиваться, все больше браузеров используют возможности производительности, продемонстрированные Mozilla, а фреймворки и библиотеки все чаще используют новые функции, будущее веб-разработки выглядит очень ярким!

Редакция: Команда webformyself.

Как создать сайт самому?

Какие технологии и знания необходимы сегодня, чтобы создавать сайты самостоятельно? Узнайте на интенсиве!

JavaScript. Быстрый старт

Изучите основы JavaScript на практическом примере по созданию веб-приложения

Начало работы с WebAssembly, используя только 14 строк на JavaScript

WebAssembly — это новая веб-технология с огромным потенциалом. Она окажет существенное влияние на то, как веб-приложения будут разрабатываться в будущем.

Но иногда мне кажется, что эта технология просто не хочет, чтобы люди её поняли… Можно сказать, даже в странной пассивно-агрессивной манере.

Когда я смотрю документацию или обучающие материалы, которых уже целая куча, то не могу не чувствовать себя фермером, который молил о дожде, чтобы потом утонуть в потопе. Технически я получил то, что хотел… просто не так, как надеялся. «Ты хочешь дождь?! О, я дам тебе дождь!»

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

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

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

Давайте разобьём на части

Всё станет намного понятнее, если мы сделаем шаг назад и рассмотрим список действий для внедрения WebAssembly в проект.

При первом взгляде на WebAssembly он может показаться просто большим комком опций и процессов. Разделение его на отдельные шаги поможет нам сформировать чёткое представление о том, что происходит:

  1. написание: напишите что-нибудь (или возьмите существующий проект) на C, C++ или Rust;
  2. компиляция: скомпилируйте этот код в WebAssembly (это даст вам бинарный wasm-файл);
  3. подключение: перенесите wasm-файл в проект;
  4. инициализация: напишите на JavaScript немного асинхронного кода, который скомпилирует и инициализирует wasm-файл так, чтобы с ним можно было взаимодействовать.

В целом, это всё. Само собой, есть разные реализации этого процесса, но в этом и суть.

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

Для нашего проекта мы напишем простую функцию на C++ (не беспокойтесь, если вы не знакомы с этим языком, код будет максимально простым). Функция будет возвращать квадрат заданного числа.

Затем мы скомпилируем это в wasm-файл с помощью онлайн-компилятора (вам не понадобится скачивать утилиты или использовать командную строку). Далее мы инициализируем эту функцию с помощью 14 строк кода на JavaScript.

Когда мы закончим, вы сможете вызвать функцию, написанную на C++ так, как если бы она была JavaScript-функцией, и вы будете поражены!

Огромное количество возможностей, которые открывает WebAssembly, просто взрывает мозг.

Написание

Давайте начнём с нашего кода на C++. Помните, что мы не будем использовать локальное окружение для написания или компиляции кода.

Вместо этого мы будем использовать онлайн-инструмент, который называется WebAssembly Explorer. Он похож на CodePen для WebAssembly и позволяет скомпилировать ваш код на C или C++ прямо в браузере и скачать wasm-файл.

После того как вы открыли WebAssembly Explorer, введите этот код на C++ в самое левое окно:

Как я и говорил, мы используем очень простой пример. Даже если вы никогда раньше не видели C или C++, то всё равно не сложно догадаться, что здесь происходит.

Компиляция

Далее кликните по кнопке compile на красной панели над вашим C++ кодом. Вот что вы увидите:

Средняя колонка содержит человеко-читаемую версию бинарного wasm-файла, которую вы только что создали. Это называется «WAT», или WebAssembly Text Format.

Справа — получившийся ассемблерный код. Довольно круто.

Я не буду разбирать результат компиляции подробно, но вы должны знать хотя бы немного о WAT-файле, чтобы двигаться дальше.

WAT существует потому, что мы, люди, обычно испытываем трудности с пониманием чистого двоичного кода. Это, по сути, слой абстракции, который помогает понимать WebAssembly-код и взаимодействовать с ним.

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

Любые функции, которые вы написали на C++, будут доступны в WebAssembly как нечто называемое export . Мы поговорим об этом немного позже, ну а сейчас вам нужно знать лишь то, что export — это то, с чем можно взаимодействовать.

Взгляните на WAT-файл и найдите там слово export . Вы увидите его дважды: в первый раз рядом со словом memory и затем снова рядом со словом _Z7squareri . О memory пока необязательно ничего знать, а вот _Z7squareri нас определённо интересует.

В коде на C++ мы назвали функцию squarer , но теперь она почему-то называется _Z7squareri . В первый раз это может сбить с толку.

Насколько я могу судить, префикс «_Z7» и суффикс «i» — это отладочные маркеры, добавленные компилятором C++. В это необязательно глубоко вникать. Вам просто нужно знать, что это произойдет, т.к. вам понадобится точное имя в JavaScript-файле, чтобы вызвать функцию, написанную на C++.

Подключение

Теперь просто нажмите на кнопку «download» в фиолетовой секции. Вы должны получить бинарный wasm-файл. Переименуйте его в squarer.wasm . Затем создайте новую папку и переместите туда файл squarer.wasm вместе с двумя другими файлами:

  • index.html (шаблонный код),
  • scripts.js (пока что пустой).

Инициализация

Теперь сложная часть. Или, по крайней мере, часть, которая ввела меня в замешательство, когда я в первый раз начал просеивать документацию.

Хотя, в конечном итоге, вы сможете подключать wasm-модули, как старые добрые ES6-модули (используя

Пишем CHIP-8 эмулятор с использованием Rust и WebAssembly (часть 2)

(Исходную статью я разбил на две части. Оригинал)
Первую часть перевода можно почитать тут
Работа с памятью
Создание интерфейса с помощью WebAssembly может быть довольно сложным. WebAssembly поддерживает только четыре базовых типа, поэтому передача чего-либо более сложного на границе WebAssembly/JavaScript требует некоторого кодирования/декодирования.

WebAssembly и JavaScript работают с общей памятью, к которой оба имеют на чтение и изменение. Данные могут быть общими через общие ячейки памяти.

Например, у эмулятора CHIP-8 всего 4Кб памяти, которая определена структурами и экспортируется следующим способом:

Во время выполнения экземпляр CPU будет размещен где-то в памяти модуля WebAssembly. Мы можем узнать где именно, используя функцию get_memory.

На стороне JavaScript, мы можем получить доступ к этой памяти с помощью exports.memory. С помощью функции get_memory, к 4Кб памяти CHIP-8 можно получить доступ так:

Когда я запускаю код выше, get_memory возвращает значение 16760, в котором компилятор Rust решил выделить эту структуру.

Загрузка ROM в память так же проста. Сброс CPU (сбрасывает регистры и т.д.), а затем происходит запись в массив programMemory:

Обратите внимание на смещение 0х200 — оно связано с загрузкой ROM с 512-байтовым смещением.

Чтение дисплея или регистра значений использует тот же подход, что и выше.

Немного Rust
Я новичок в Rust(около двух недель), потому я не привожу много своего кода. Боюсь показаться глупым из-за очевидных ошибок.

Мой опыт использования Rust очень вдохновляет. Язык гораздо более строгий, чем те языки что я использовал до этого. Это другой конец палки, если сравнивать его с JavaScript. Кроме того, Rust современен и элегантен. По-моему, самая сложная концепция, к которой придется привыкнуть — это концепция владения Rust. Я работал с несколькими методами управления памятью (сборщик мусора, автоматический подсчет ссылок), однако концепция владения Rust, где у вас есть единственное изменяемое связывание с ресурсом, нова для меня.


Часть эмулятора CHIP-8, которая по-моему получилось особенно хорошо, это метод execute_opcode. Инструкции CHIP-8 имеют длину 16 бит, как описано в этой технической справочной информации.

Для некоторых инструкций первый полубайт (4 бита) представляет код операции, а остальные полубайты кодируют данные кода операции. Например, операция «jump» обновляют счетчик программы с определенным адресом. Он кодируется как 0x1nnn, где первое значение 0x1 кодирует операцию перехода, а следующие три(nnn) — представляют адрес.

Сопоставление шаблонов с диапазонами в Rust — идеальный инструмент для реализации этого. Вот пример, который использует соответствие диапазонов для реализации инструкции перехода:

Лучшие webassembly вопросы ИТ разработчиков

В чем разница между asm.js и WebAssembly?

Я недавно читал об asm.js и WebAssembly:http://ejohn.org/blog/asmjs-javascript-compile-target/https://brendaneich.com/2015/06/from-asm-js-to-webassembly/Я вс.

Как я могу вернуть строку JavaScript из функции WebAssembly

функции здесь . именно они выполняют работу по передаче / возвращению массива.

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

Это выглядит многообещающе. И это даже новее, чем WebAssembly, чей MVP был выпущен менее месяца назад.

Если вы посмотрите более тщательно, почему Python-to-C (или Python-to-C ++) был настолько хитрым, вы можете увидеть подробные причины этого краткого ответа, но я думаю, что это выходит за рамки вашего вопроса.

ал, что можно преобразовать код Python 2.7 в веб-сборку, но я не могу найти полное руководство о том, как это сделать. До сих пор я скомпилировал программу на C для Web Assembly с использованием Emscripten и всех его необходимых компонентов, .

Из-за искажения имени в c ++ я обнаружил, что начать работать с C проще.

оложим, у меня есть простой, автономный файл C ++ (math.cpp) нравится: int add(int x, int y) < return x + y; >Как бы я скомпилировал его в WebAssembly (math.wasm)? Примечание: я использую цепочку инструментов Clang.

Был разрешен в текущей версии LLVM.

ли способ получить доступ к указателям на функции, живущим в модуле WebAssembly? Например, с учетом следующего «модуля», скомпилированного в WebAssembly: extern void set_callback(void (*callback)(void *arg), void *arg); static .

Используйте сгенерированные файлы .bc для этих библиотек в качестве аргументов компоновщика для команды em ++, и это должно работать.

аюсь скомпилировать некоторый код C, который использует OpenSSL с emscripten, но я получаю нерешенные предупреждения о символах, такие как: warning: unresolved symbol: SHA256_Init warning: unresolved symbol: SHA256_Final warning: unresolved .

@ GeorgeJempty Я только что запустил его на JSBench, и я получаю как минимум 20-кратное увеличение в Safari, 6-кратное — в Chrome. Если это действительно становится узким местом в сети, браузеры будут оптимизировать его.

держкой WebAssembly, входящей во все новые основные браузеры, как я могу проверить, поддерживает ли ее текущий браузер, который посещает мой сайт?

Это всего лишь пример, часть гораздо большего модуля. Проблема с производительностью заключается в том, почему я до сих пор не вижу демонстрацию, которая заставляет меня говорить: «Ух ты, ты никогда не сможешь сделать это в JS», пока я не увижу, что заголовки, рекламирующие webAssembly как «Изменитель игры», — просто ажиотаж.

длину строки на 300 * медленнееСначала я прочитал ответ наПочему моя функция WebAssembly медленнее, чем эквивалент в JavaScript? [https://stackoverflow.com/q/46331830/3877726] Но это пролило немного света на проблему, и я потратил много .

Вы должны сделать то же самое, что и связанный вопрос, но в обратном порядке. Вам нужно будет выбрать кодировку (например, UTF-8 или UTF-16), поместить эти закодированные данные в буфер, решить, как передать этот указатель и длину через границу, а затем «просто сделать это».

я есть эта простая функция Rust: #[no_mangle] pub fn compute(operator: &str, n1: i32, n2: i32) -> i32 < match operator < "SUM" =>n1 + n2, «DIFF» => n1 — n2, «MULT» => n1 * n2, «DIV» => n1 / n2, _ => 0 > >Я успешно компилирую это в WebAssembly, .

target_link_libraries (mainTest crypto) после этого все работало без предупреждений.

вание OpenSSL с веб-сборкой Прежде чем задать этот вопрос, я просто хочу сказать, что я сделал домашнее задание. Вопрос очень похож на тот, что уже задавался здесь, т.е.Как связать OpenSSL с .

WebAssembly — всё по этой теме для программистов

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.

Efficient and fast

The Wasm stack machine is designed to be encoded in a size- and load-time-efficient binary format. WebAssembly aims to execute at native speed by taking advantage of common hardware capabilities available on a wide range of platforms.

WebAssembly describes a memory-safe, sandboxed execution environment that may even be implemented inside existing JavaScript virtual machines. When embedded in the web, WebAssembly will enforce the same-origin and permissions security policies of the browser.

Open and debuggable

WebAssembly is designed to be pretty-printed in a textual format for debugging, testing, experimenting, optimizing, learning, teaching, and writing programs by hand. The textual format will be used when viewing the source of Wasm modules on the web.

Part of the open web platform

WebAssembly is designed to maintain the versionless, feature-tested, and backwards-compatible nature of the web. WebAssembly modules will be able to call into and out of the JavaScript context and access browser functionality through the same Web APIs accessible from JavaScript. WebAssembly also supports non-web embeddings.

Информационный портал по безопасности

Знакомство с WebAssembly

Эта статья основана на моём выступлении на ITSubbotnik, прошедшем в Рязани 14 октября 2020 года. На русском пока что довольно мало материала на эту тему, надеюсь что статья будет вам полезна.

Disclaimer: Автор не является экспертом ни в WebAssembly, ни в javascript. Данная статья есть компиляция мыслей и идей, полученных из выступлений других людей на данную тему, плюс эпизодического опыта изучения WebAssembly в течение нескольких месяцев.

Проблема

Давайте разберёмся сначала, какую проблему или задачу пытались решить, создавая WebAssembly.

Проблема далеко не новая, фактически это — быстро исполнять код в браузере.

Но не всё так просто, постепенно так сложилось, что помимо самой проблемы, у нас есть ещё несколько сопутствующих требований:

  • Быстрее чем javascript — в идеале, со скоростью света родного кода нашего процессора.
  • Zero configuration — решение «из коробки», без установки, нужен только браузер.
  • Безопасно — новая технология не должна создавать новых угроз.
  • Кросс-платформенно — у нас есть несколько платформ, включая мобильные, несколько операционных систем.
  • Удобно для разработчиков — нужны удобные средства разработки и отладки.

Ситуация

В попытке решения этой проблемы у нас есть один победитель, и это javascript.

Проигравшие (далеко не полный список):

  • ActiveX — технология позволяла делать вообще всё, безо всякого sandbox, соответственно представляла реальную угрозу безопасности.
  • Flash — в 2020 году Adobe объявила о планах прекращения поддержки Flash.
  • Silverlight

и другие плагины

Другие попытки решения:

  • NaCl — Native Client — инициатива от Google, появилась в 2011 году; не нашла поддержки других браузеров кроме Chrome.
  • PNaCl — Portable Native Client — LLVM IR subset.
  • asm.js — Mozilla, появилась в 2013 году — ниже рассмотрим подробнее.

В целом, все попытки решения можно разбить на две группы:

Решение 1: Родной код прямо в браузере

Примеры: ActiveX, NaCl

Что плохо: нет портируемости, потенциальные или реальные проблемы с безопасностью.

Решение 2: Код для виртуальной машины

Примеры: Java Applets, Silverlight и др.

Что плохо: нужен плагин и/или runtime => нет zero configuration

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

Что не так с javascript?

С javascript всё хорошо. Но если смотреть на рост его производительности с годами, то мы увидим что он сейчас находится на втором «плато» S-образной кривой. Сначала производительность была небольшой и росла постепенно, с появлением V8 мы увидели резкий скачок, который уже достаточно давно вновь перешёл в плавный рост.

Посмотрим как работают современные движки javascript.

Прежде всего, исходный код (текст на JS) проходит через парсер, в результате возникает внутреннее представление кода — абстрактное синтаксическое дерево. Дальше работает интерпретатор. Отдельные функции при исполнении преобразуются в байт-код — по сути, последовательность вызовов внутренних функций интерпретатора. При этом накапливается статистика использования JS-функций. Если для какой-то отдельной функции преоделён порог вызовов, то принимается решение о том, что её нужно оптимизировать и она передаётся компилятору. Компилятор генерирует машинный код, который сильно завязан на типы входных значений.

Допустим, у нас есть функция с двумя аргументами: foo(a, b), и мы вызываем её много раз с числовыми значениями параметров. В некоторый момент функция будет передана компилятору и станет выполняться быстрее. Допустим, мы вызовем её со строковым аргументом. В результате, движок выполнит «деоптимизацию»: передаст функцию от компилятора обратно интерпретатору, а готовый машинный код будет выброшен.

Что я хочу этим сказать? Разработчики javascript движков делают отличную работу и спасибо им за это. javascript вовсе не плох, но у него есть внутренние ограничения, которые уже не позволят сделать его радикально быстрее.

asm.js

Ещё одна интересная инициатива, уже от Mozilla Foundation, которая подводит нас вплотную к теме WebAssembly. Появилась она в 2010 году, а в 2013 стала публично доступна.

Идея заключается в том, что создано подмножество javascript, в которое можно компилировать код из C и C++ с помощью специального компилятора Emscripten.

Поскольку это подмножество javascript, то такой код будет исполняться в любом браузере. Кроме того, основные современные браузеры уже давно умеют быстро распознавать asm.js и эффективно компилировать его в родной код процессора. В сравнении с родным кодом, полученным непосредственно из C/C++, код полученный из asm.js код медленнее всего в 1,5-2 раза (50-67 %).

Для простейшей функции на C/C++ код asm.js выглядит так:

Здесь ‘use asm’ это директива, показывающая JS-движку что код ниже это asm.js, и конструкции вида |0 показывают, что работа идёт с целыми числами (логическое ИЛИ с нулевым значением обнуляет дробную часть Number).

Цели разработки WebAssembly

  • Скорость — почти как родной код.
  • Эффективность — бинарный формат, быстрый парсинг и компиляция.
  • Портируемость — все браузеры и операционные системы.
  • Безопасность — запуск в sandbox.
  • Удобство отладки — поддержка отладки в браузерах, отладчик есть уже сейчас.
  • Открытый стандарт — то есть это уже не инициатива отдельной компании, пытающейся «перетянуть одеяло на себя». Стандарт уже принят, в 2020 году.

Так что же такое WebAssembly?

  • Бинарный формат
  • НЕ язык программирования, а байт-код

Мы же не называем Java-байткод языком программирования.

Загружается в браузер и исполняется в браузере.

Формально, WebAssembly исполняется javascript-движком, а не самим браузером, поэтому есть и другие варианты исполнения, например, под NodeJS.

Исполняется виртуальной машиной

Это простая стековая машина с памятью, простота позволяет легко реализовать её для любого современного процессора.

НЕ имеет ничего общего с Web, кроме того что общается с внешним миром через javascript.

Действительно, WebAssembly это просто виртуальная машина, имеющая память и исполняющая инструкции.

С чего начать? Hello World

Освоение WebAssembly я очень советую начать с онлайнового инструмента WasmFiddle .

(Сам я начал с Emscripten и понял свою ошибку лишь спустя время.)

Слева вверху исходный код, слева внизу результат компиляции по кнопке Build (сейчас видно текстовое представление), справа вверху код для запуска и справа внизу результат запуска по кнопке Run.

В качестве примера я использовал простой код для расчёта числа Фибоначчи (да, опять он :), не сказать чтобы хороший код, просто первый попавшийся нагугленый вариант:

Немного про текстовое представление (WAST). Как уже говорилось, WebAssembly это бинарный формат, на выходе компиляции мы получаем WASM-файл. Текстовое представление всегда можно получить из WASM-файла, оно позволяет разобраться в том, что именно содержит сборка, какие таблицы и код. Также это представление используется для отладки.

В данном случае, по текстовому представлению мы видим, что выделяется 1 страница памяти (каждая страница = 64 Кбайт), наружу видны (экспортируются) память и функция fib, а дальше идёт определение этой функции, то есть собственно её реализация.

Начало текстового представления этой сборки выглядит так:

Если собрать всё вместе, то минимальный javascript-код для запуска примера выглядит примерно так:

Здесь готовый WASM описывается в коде в виде массива чисел, но в реальной жизни конечно WASM-файл будет довольно намного больше, и мы будем подгружать его с сервера.

Исполнение WebAssembly в браузере выглядит так. Браузер как обычно загружает HTML-страницу, с которой выполняется javascript, который уже выполняет загрузку WebAssembly — получается «модуль» (WebAssembly module), затем создаёт экземпляр модуля, после чего можно вызывать для этого экземпляра экспортируемые им функции.

Обратите внимание здесь на серую стрелку: изнутри WebAssembly можно вызывать функции javascript.

Рассмотрим это подробнее на диаграмме последовательности:

Здесь мы сначала из javascript вызываем WebAssembly, затем из WebAssembly вызываем функцию javascript.

Во втором вызове здесь я показал то, как WebAssembly пользуется любыми API (например, DOM / WebGL итд.). Это возможно, но не напрямую, такие вызовы тоже происходят только через javascript. Очевидно, здесь возникает «бутылочное горлышко»: если мы будем интенсивно работать с API из WASM, то будем терять много времени на «прокидывании» этих вызовов через javascript.

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

Весь блок памяти доступен из javascript, просто как массив байтов (и кроме того, как массив 16- и 32-разрядных слов, как массив 16- и 32-разрядных float-значений). Причём, память из javascript доступна как на чтение так и на запись.

Emscripten

Emscripten это основной компилятор для получения asm.js и WebAssembly из C/C++. (Существуют также компиляторы в WASM из других языков, например из Rust и TypeScript.) Здесь я буду рассматривать использование Emscripten под Windows, но не думаю что для других систем будут существенные различия.

Говоря об Emscripten, стоит немного рассказать о Low Level Virtual Machine (LLVM).

LLVM это семейство компиляторов. Основная идея LLVM это разделение компиляции на frontend и backend. Frontend-компилятор занимается компиляцией из исходного кода во внутреннее представление (Intermediate Representation, IR). IR это код для некоторой виртуальной машины. Backend-компилятор занимается уже преобразованием IR в код для конкретной платформы, например, часто используется backend для x86 и x86-64. Если нужен компилятор с другого языка программирования, то пишется только новый frontend. Если нужна компиляция под новую платформу, то пишется новый backend.

Emscripten задействует LLVM для компиляции из C/C++, и предоставляет свои backend-компиляторы для сборки в asm.js и WebAssembly.

Установка Emscripten

Установка Emscripten проходит довольно просто, в моём случае это было под Windows, и мне даже не понадобилось ничего компилировать из исходников.

  1. Загружаем отсюда: http://emscripten.org/
  2. Распаковываем в отдельную папку, в моём случае C:binemsdk
  3. Открываем командную строку, переходим в папку emsdk и выполняем три команды:

Всё установлено и настроено, можем компилировать.

Выполнив команду emsdk list , вы получите список всех версий всех инструментов, доступных для установки, с отметками того что выбрано сейчас.

Компиляция в asm.js

Посмотрим как можно собрать код с помощью Emscripten, начнём с asm.js.

Пример тот же что и выше, немного модифицированный для Emscripten (fib.c):

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

Для компиляции я использую следующий командный файл:

Здесь emcc это собственно Emscripten, -O1 опция оптимизации, fib.c что компилировать, -o fib.html куда компилировать, и дальше опции -f чтобы отключить то что нам не нужно.

На выходе компиляции мы получаем HTML-файл (fib.html), включающий javascript для запуска скомпилированного кода:

Также мы получили файл fib.js, в недрах которого можно найти функцию fib() и её вызов в main():

Кроме того, генерируется двоичный файл fib.html.mem — это «образ памяти», то как выглядит память перед запуском программы, здесь все константы и глобальные переменные.

Открыв fib.html мы увидим вот такую картину:

Это стандартный вид результата для Emscripten. Чёрный прямоугольник по центру это вывод «консоли» (stdout), туда в частности выводится printf() . Чёрный прямоугольник вверху это canvas; Emscripten не знает нужен ли он вам, но создаёт его здесь на всякий случай.

Компиляция в WebAssembly

Для компиляции в WebAssembly нам вообще не нужно менять исходник на C/C++ (и это прекрасно!).

Мы немного изменяем только командную строку вызова компилятора:

Главное отличие здесь это добавлении опции -s WASM=1 .

Остальные -s и -f добавлены в попытках объяснить Emscripten что нам НЕ нужно. Emscripten умеет слишком много, и поэтому «на всякий случай», «вдруг понадобится» он много чего добавляет в результирующие файлы.

В результате компиляции мы также получаем fib.html, плюс fib.js (набор сервисных функций Emscripten), плюс наконец-то fib.wasm:

В начале WASM-файла стоит байт 00 и затем символы «asm», по этим первым четырём байтам можно определить, что мы загружаем именно wasm, а не какую-нибудь страницу-заглушку с кодом ошибки. Следующие 4 байта это номер версии, в данном случае 1.0.

Отдельного файла для образа памяти не генерируется, константы и глобальные переменные включены в тот же WASM-файл.

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

Давайте посмотрим что у нас есть в плане отладки. Открыв инструменты разработчика Chrome (F12), переходим в Sources и там увидим новый раздел «wasm», в котором среди набора блоков можем найти нашу функцию, можем поставить там точку останова, остановиться на ней и пошагать в отладчике.

Как видите, для отладки используется текстовое представление (WAST), о котором я говорил выше.


Теперь давайте откомпилируем тот же код с отладочной информацией, для этого в командную строку emcc добавим опцию -g . В результате компилятор сгенерирует нам ещё два файла: fib.wast и fib.html.map.

В файле текстового представления fib.wast есть не только код, но и отсылки к исходнику на C/C++:

Посмотрим что нам это даст в плане отладки. Обновив страницу, в разделе Sources мы теперь увидим наш исходник fib.c, можем поставить в нём точку останова, остановиться на ней, просмотреть локальные переменные и пошагать отладчиком по коду.

Возможности Emscripten

Emscripten развивается с 2010 года и уже много чего умеет. В данном случае речь уже не о компиляторе, а о поддержке популярных библиотек, используемых из кода на C/C++. Поддерживаются:

  • Стандартные библиотеки С/С++
  • SDL 2 — ввод (клавиатура/мышь/джойстики), видео, звук
  • OpenGL, EGL — 2D/3D-графика, реализуются через WebGL
  • OpenAL — звук

И другие возможности:

  • Эмуляция файловой системы — многие программы на C/C++ интенсивно работают с файлами, можно оставить этот код как есть; см. Emscripten — File System Overview
  • EM_ASM(«JS code») — выполнение произвольного javascript-кода, сформированного в виде строки
  • Workers

Более сложный пример

У меня есть свой хобби-проект эмулятора старого советского компьютера, написанный на C++, я его описывал вот в этой статье . С тех пор я успел его несколько дописать, а также портировать под Qt (Windows/MacOS/Linux). Так что у меня уже было выделено ядро эмуляции (

7 килострок), которое собиралось под разными компиляторами. Собственно я и начал изучение WebAssembly с того, что компилировал этот эмулятор с помощью Emscripten. До первого удачного запуска у меня ушло два вечера после работы, я считаю это неплохой результат, говорящий о том, что порог вхождения в тему относительно низкий. Большая часть работы была связана с javascript: как из JS вызывать методы WASM, как передавать параметры, как отрисовывать canvas итп.

Кстати, экран эмулируемой машины формируется полностью внутри WASM, в виде сплошного блока памяти, с форматом «пикселей», подходящем для canvas. Наружу в javascript передаётся только адрес готового «экрана». В javascript остаётся только скопировать этот блок памяти в canvas.

Также в какой-то момент я решил «для полноты картины» собрать этот эмулятор ещё и под asm.js. Сделал себе кофе, выделил на это пару свободных часов, и меньше чем через 15 минут эмулятор уже заработал. Это было как бы неожиданно. Фактически, всё что пришлось сделать, это посмотреть различия в сгенерированном HTML-файле и перенести добавленный javascript-блок куда нужно. Различие было лишь в том, что для asm.js должен загружаться .mem-файл, образ памяти с константами и глобальными переменными. В остальном все вызовы выполнялись точно так же, и готовая страница выглядела и работала в точности так же, разве что немного медленнее.

Итак, подводя итоги по Emscripten. Я убедился в том, что из одного и того же кода он генерирует результат в виде asm.js и в виде WebAssembly, полученный результат выглядит и работает в точности одинаково (кроме скорости конечно). Порог вхождения до получения реального результата оказался относительно низким.

С другой стороны, Emscripten довольно сложный и «нафаршированный» инструмент. В результат компиляции он включает массу вещей которых вы не ожидаете, но которые могут вам пригодится. Поэтому даже для небольших по объёму исходников генерируется большой объём результирующего кода. Часть таких вещей можно отключить опциями командной строки , часть нет.

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

Текущее состояние WebAssembly

Новости WebAssembly в 2020 году:

  • Март 2020 — WebAssembly Cross-browser consensus and end of Browser Preview
  • Май 2020 — Команда Chromium отказалась от PNaCl в пользу WebAssembly https://blog.chromium.org/2020/05/goodbye-pnacl-hello-webassembly.html
  • Сентябрь — Вышел Safari 11 с поддержкой WebAssembly https://webkit.org/blog/7956/new-webkit-features-in-safari-11/

Поддержка в браузерах

На начало октября 2020 года ситуация выглядела примерно так:

Версия Edge привязана к версии операционной системы. Вместе с Windows 10 Fall Creators Update мы получаем Edge 16, в котором WebAssembly работает сразу, уже не нужно ничего включать в настройках.

Для браузеров, не поддерживающих WebAssembly, предполагается использовать т. н. «polyfill», то есть автоматическое преобразование WASM в код, который может выполняться в данном браузере. В частности, был сделан прототип, эффективно выполняющий преобразование WebAssembly в asm.js. Но пока я не видел примеров реального применения такого подхода.

Будущее WebAssembly

Ряд вещей над которыми команда WebAssembly работает сейчас :

Текущая реализация WASM полностью однопоточная.

SIMD

Поддержка SIMD позволит существенно ускорить однотипную обработку на больших объёмах данных — изображения, видео, звук.

  • Exceptions
  • Garbage Collection

    Реализация GC позволит компилировать под WASM с языков с автоматическим управлением памятью. Это возможно и сейчас, но только в варианте когда GC реализуется на C/C++ внутри WASM.

    Производительность

    Вопрос по производительности на самом деле довольно сложный. Потому что не всегда WebAssembly работает быстрее того же javascript или asm.js.

    Например, посмотрите сравнения из javascript vs WebAssembly easy benchmark . На первом же тесте collisionDetection у меня получается что WASM даёт 88% от JS. А допустим на следующем тесте Fibonacci WASM выдаёт гораздо лучший результат, в 3 раза быстрее чем JS.

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

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

    WebAssembly теряет в производительности на обращениях к памяти: каждое такое обращение делает проверку на выход за границы доступного блока памяти.

    WebAssembly может существенно выигрывать за счёт типа целых переменных. В JS у нас есть только тип Number, фактически всегда 64-разрядный с плавающей точкой, и целые числа это плавающее число без дробной части. При компиляции в JS-движке, для целых чисел используется 64-разрядный целый тип. В WASM мы сами выбираем разрядность типа, и если мы используем 32-разрядный целый тип, операции над которым немного быстрее чем над 64-разрядным целым, то мы получаем здесь «нечестное» преимущество в скорости вычислений.

    В целом, у меня сложилось мнение, что нет такого что «в среднем WebAssembly обеспечивает 10-15% прирост скорости», нет никакого «в среднем», для каждого алгоритма нужно тестом определять, получите ли вы прирост скорости, применив WASM. Но в целом, можно предсказать что для интенсивных вычислений, скорее всего, WebAssembly даст какой-то более или менее ощутимый прирост производительности. Ну и кроме того, видно что уже даже за последние полгода скорость WASM несколько выросла с выходом новых версий браузеров.

    Заключение

    Применение WebAssembly

    • Уменьшить время загрузки
    • Поднять скорость вычислений
    • Использовать готовый код на C/C++

    Варианты использования

  • Применять WASM уже сейчас, если вы к этому готовы
  • Использовать asm.js сейчас, перейти на WASM в будущем
  • Отдавать asm.js либо WASM, в зависимости от браузера

    Ссылки

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

    Компиляция C в WebAssembly без Emscripten

    Компилятор — часть Emscripten. А что, если удалить все свистелки и оставить только его?

    Emscripten необходим для компиляции C/C++ в WebAssembly. Но это гораздо больше, чем просто компилятор. Цель Emscripten в том, чтобы полностью заменить ваш компилятор C/C++ и запустить в вебе код, который изначально не предназначен для Сети. Для этого Emscripten эмулирует всю операционную систему POSIX. Если программа использует fopen(), то Emscripten предоставит эмуляцию файловой системы. Если используется OpenGL, то Emscripten предоставит С-совместимый контекст GL, поддерживаемый WebGL. Это немалая работа, и немало кода, который придётся внедрить в итоговый пакет. Но можно ли просто… удалить его?

    Собственно компилятором в наборе инструментов Emscripten является LLVM. Именно он переводит код C в байт-код WebAssembly. Это современный модульный фреймворк для анализа, трансформации и оптимизации программ. LLVM модульный в том смысле, что он никогда не компилирует прямо в машинный код. Вместо этого встроенный фронтенд-компилятор генерирует промежуточное представление (IR). Это промежуточное представление, собственно, и называется LLVM, аббревиатура от Low-Level Virtual Machine, отсюда и название проекта.

    Затем бэкенд-компилятор выполняет перевод IR в машинный код хоста. Преимущество такого строгого разделения заключается в том, что новые архитектуры поддерживаются «простым» добавлением нового компилятора. В этом смысле WebAssembly — лишь одна из многих целей компиляции, которые поддерживает LLVM, и в течение некоторого времени он активировался специальным флагом. Начиная с LLVM 8 цель компиляции WebAssembly доступна по умолчанию.

    На MacOS вы можете установить LLVM с помощью homebrew:

    Проверяем поддержку WebAssembly:

    Кажется, мы готовы!

    Компиляция C трудным путём

    Примечание: здесь рассмотрим некоторые низкоуровневые форматы RAW WebAssembly. Если вам их трудно понять, это нормально. Хорошее использование WebAssembly не требует обязательного понимания всего текста в этой статье. Если ищете код для копипаста, см. вызов компилятора в разделе «Оптимизация». Но если вам интересно, продолжайте читать! Ранее я написал введение в чистый Webassembly и WAT: это основы, необходимые для понимания этого поста.

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

    Какой умопомрачительный инженерный подвиг! Особенно потому что программа называется add, а на самом деле она ничего не add (не добавляет). Что более важно: программа не использует стандартную библиотеку, а из типов здесь только ‘int’.

    Превращаем C во внутреннее представление LLVM

    Первый шаг — превратить нашу программу C в LLVM IR. Это задача фронтенд-компилятора clang , который установился с LLVM:

    И в результате мы получаем add.ll с внутренним представлением LLVM IR. Я показываю его только ради полноты картины. При работе с WebAssembly или даже clang вы как разработчик на C никогда не вступаете в контакт с LLVM IR.

    LLVM IR полна дополнительных метаданных и аннотаций, что позволяет компилятору принимать более обоснованные решения при генерации машинного кода.

    Превращаем LLVM IR в объектные файлы

    Следующий шаг — вызов бэкенд-компилятора llc , чтобы сделать из внутреннего представления объектный файл.

    Выходной файл add.o — это уже валидный модуль WebAssembly, который содержит весь скомпилированный код нашего файла C. Но обычно вы не сможете запустить объектные файлы, поскольку в них отсутствуют существенные части.

    Если бы в команде мы опустили -filetype=obj , то получили бы ассемблер LLVM для WebAssembly, человекочитаемый формат, который в чём-то похож на WAT. Однако инструмент llvm-mc для работы с такими файлами ещё не полностью поддерживает формат и часто не может обработать файлы. Поэтому дизассемблируем объектные файлы постфактум. Для проверки этих объектных файлов нужен специфический инструмент. В случае WebAssembly это wasm-objdump , часть WebAssembly Binary Toolkit или wabt для краткости.

    Выдача показывает, что наша функция add() находится в этом модуле, но она также содержит разделы custom с метаданными и, что удивительно, несколько импортов. На следующем этапе компоновки разделы custom будут проанализированы и удалены, а с импортом разберётся компоновщик (линкер).

    Компоновка

    Традиционно задачей компоновщика является сборка нескольких объектных файлов в исполняемый файл. Компоновщик LLVM называется lld , и он вызывается с указанием целевой символической ссылки. Для WebAssembly это wasm-ld .

    В результате получается модуль WebAssembly размером 262 байта.

    Запуск

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

    Если всё нормально, вы увидите в консоли DevTool число 17. Мы только что успешно скомпилировали C в WebAssembly, не трогая Emscripten. Также стоит отметить, что здесь нет никакого связующего кода для настройки и загрузки модуля WebAssembly.

    Компиляция C немного попроще

    Для компиляции C в WebAssembly мы сделали немало шагов. Как я уже сказал, в образовательных целях мы рассмотрели подробно все этапы. Давайте пропустим человекочитаемые промежуточные форматы и сразу применим компилятор C как швейцарский армейский нож, как он и был разработан:

    Здесь мы получаем такой же файл .wasm , но одной командой.

    Оптимизация

    Посмотрим на WAT нашего модуля WebAssembly, запустив wasm2wat :

    Ничего себе, какой большой код. К моему удивлению, модуль использует память (что видно по операциям i32.load и i32.store ), восемь локальных и несколько глобальных переменных. Вероятно, вручную можно написать более лаконичную версию. Эта программа такая большая, потому что мы не применили никаких оптимизаций. Давай сделаем это:

    Примечание: технически, оптимизация при компоновке (LTO) не даёт никаких преимуществ, поскольку мы компонуем только один файл. В больших проектах LTO поможет заметно уменьшить размер файла.

    После выполнения этих команд файл .wasm уменьшился с 262 до 197 байт, а WAT тоже стал намного проще:

    Вызов стандартной библиотеки

    Использование C без стандартной библиотеки libc кажется довольно грубым. Логично добавить её, но буду честен: это не будет легко. На самом деле мы напрямую не вызываем в статье никаких библиотек libc. Есть несколько подходящих, особенно glibc, musl и dietlibc. Однако большинство этих библиотек предполагается запускать в операционной системе POSIX, которая реализует определённый набор системных вызовов. Поскольку у нас в JavaScript нет интерфейса ядра, нам придётся самостоятельно реализовать эти системные вызовы POSIX, вероятно, через JavaScript. Это сложная задача и я не собираюсь этим тут заниматься. Хорошая новость в том, что именно этим для вас занимается Emscripten.

    Конечно, не все функции libc полагаются на системные вызовы. Такие функции, как strlen() , sin() или даже memset() , реализованы в простом C. Это означает, что вы можете использовать эти функции или даже просто скопировать/вставить их реализацию из какой-нибудь упомянутой библиотеки.

    Динамическая память

    Без libc нам недоступны фундаментальные интерфейсы C, такие как malloc() и free() . В неоптимизированном WAT мы видели, что компилятор в случае необходимости использует память. Это означает, что мы не можем просто использовать память, как нам нравится, не рискуя её повредить. Нужно понять, как она используется.

    Модели памяти LLVM

    Способ сегментации памяти WebAssembly немного удивит опытных программистов. Во-первых, в WebAssembly технически допустим нулевой адрес, но часто он всё равно обрабатывается как ошибка. Во-вторых, стек приходит первым и увеличивается вниз (к более низким адресам), а куча появляется потом и растёт вверх. Причина в том, что память WebAssembly может увеличиться во время выполнения. Это означает, что нет фиксированного конца для размещения стека или кучи.

    Вот макет wasm-ld :

    Стек растёт вниз, а куча — вверх. Стек начинается с __data_end , а куча — с __heap_base . Потому что стек размещается первым, он ограничен максимальным размером, установленным при компиляции, то есть __heap_base минус __data_end

    Если вернуться и посмотреть на раздел globals в нашем WAT, мы найдём эти значения: __heap_base установлен в 66560, а __data_end — в 1024. Это означает, что стек может вырасти максимум до 64 КиБ, что не много. К счастью, wasm-ld позволяет изменить это значение:

    Сборка аллокатора

    Известно, что область кучи начинается с __heap_base . Поскольку функция malloc() отсутствует, мы знаем, что следующую область памяти можно спокойно использовать. Мы можем разместить там данные как угодно, и не нужно бояться повреждения памяти, поскольку стек растёт в другую сторону. Однако свободная для всех куча может быстро засориться, поэтому обычно требуется какое-то динамическое управление памятью. Один из вариантов — взять полноценную реализацию malloc(), такую как реализация malloc от Дага Ли, которая используется в Emscripten. Есть ещё несколько небольших реализаций с различными компромиссами.

    Но почему бы не написать собственный malloc() ? Мы так глубоко увязли, что это уже без разницы. Один из простейших — bump-аллокатор: он супербыстрый, чрезвычайно маленький и простой в реализации. Но есть и недостаток: вы не можете освободить память. Хотя на первый взгляд такой аллокатор кажется невероятно бесполезным, но при разработке Squoosh я столкнулся с прецедентами, где он стал бы отличным выбором. Концепция бамп-аллокатора заключается в том, что мы храним начальный адрес неиспользуемой памяти как глобальный. Если программа запрашивает n байт памяти, мы передвигаем маркер на n и возвращаем предыдущее значение:

    Глобальные переменные из WAT фактически определяются wasm-ld , так что мы можем получить к ним доступ из нашего кода C как к обычным переменным, если объявим их extern . Итак, мы только что написали собственный malloc() … в пяти строчках C.

    Примечание: наш бамп-аллокатор не полностью совместим с malloc() из C. Например, мы не даём никаких гарантий выравнивания. Но он достаточно хорошо и работает, так что.

    Использование динамической памяти

    Для проверки давайте сделаем функцию C, которая принимает массив чисел произвольного размера и вычисляет сумму. Не очень интересно, но это заставляет использовать динамическую память, так как мы не знаем размер массива во время сборки:

    Функция sum(), надеюсь, довольно понятна. Более интересный вопрос заключается в том, как передать массив из JavaScript в WebAssembly — в конце концов, WebAssembly понимает только числа. Общая идея состоит в том, чтобы использовать malloc() из JavaScript, чтобы выделить кусок памяти, скопировать туда значения и передать адрес (число!) где находится массив:

    После запуска вы должны увидеть в консоли DevTools ответ 15, что действительно является суммой всех чисел от 1 до 5.

    WebAssembly: бинарный формат скоро во всех браузерах страны

    WebAssembly (https://github.com/WebAssembly/design) is a new format for native programs on the web. It aims to support everything that asm.js supports, but allows the VM to sidestep the JS parsing and profiling pipeline entirely. This is a good thing for the VM — less work to support native code.

    Although WebAssembly will have polyfill to asm.js, we should support it natively by:

    — Having a WebAssembly baseline JIT that’s used for fast start-up and some basic execution count profiling.
    — An LLVM backend that uses the FTL’s LLVM glue and compiler plan scheduling for hot code.

    This standard has broad support, and we should continue to participate in discussions about how to make it great.

    Сейчас единственный способ писать client-side — использовать JS или любой другой язык, который будет транслироваться в JS. Что геморрно, ибо генерировать JopaScript не очень удобно, да и браузеры не в восторге его парсить. WebAssembly — бинарный формат, который проще как генерировать, так и парсить (Из FAQ: исходники по прежнему можно будет просматривать в читаемом виде в developer tools).

    В краткосрочной перспективе (в качестве Proof of Concept или MVP) формат будет пригоден для использования под web С/C++ (языки без GC). При чём, (в том числе) можно будет линковать модули написанные на этих низкоуровневых языках из обычного JS. В дальнейшем планируется добавить поддержку других языков, реализовав garbage collected объекты.

    Я ни в коем случае не специалист, но не будет ли это жутковатым решетом?

    А какая разница? Сейчас браузер исполняет JS, с этой хренью он точно так же будет исполнять бинарник. Права те же. Ничего не меняется.
    Ну кроме возможности писать на Си.
    Так что это скорее хорошо.

    ЕМНИП всякие цги-бин можно и так на си писать. Эдик вроде как-то хвастался давно, что на сях пишет в браузер.

    Че за бесконечная череда полумер, давайте сразу отдавать по ftp бинарник и запускать. Сначала в песочнице, потом, когда расслабятся, разрешить ее отключать кнопкой «сделать быстрее». А то какие-то браузеры, JS, как будто это какое-то отношение имеет к гипертексту и протоколу для его отдачи.

    Разумеется можно, только вот кросплатформенность.
    И мы сейчас говорим про код, исполняющийся на стороне клиента. На стороне сервера хоть на форте пиши.
    А тут получим вместо ктулхумерзкого ЖС — любой язык. Переводишь его в байткод (жаба, привет) и радуешься жизни.

    cgi-bin — это про серверную сторону. WebAssembly — для клиенткой (браузер пользователя). Поэтому рекламная «фишка» JS — «один язык для сервера и клиента» будет (я надеюсь) актуальна для любого языка.

    Там рантайм адового размера будет, как и все что связано с asmjs.

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

    Слушай, а бинарник под мой powerPC ты уже собрал?
    Бинарник это хорошо, но, как показывает практика, для многих даже в масштабе х86 тяжко перейти на АМД64, а ты говоришь про кучу платформ.
    «Виртуальная машина» вполне исправит ситуацию.

    Транслятор уже есть, зачем нам твоя плохо оттестированная неуниверсальная машина?

    WebAssembly делается совместными усилиями Google, Microsoft, Firefox.

    Поэтому рекламная «фишка» JS — «один язык для сервера и клиента» будет (я надеюсь) актуальна для любого языка.

    Уже лет семь не пойму, в чем проблема? Выкиньте из этой цепочки никому не нужный браузер и пишите сервер и клиент хоть на тикле.

    Ты такооой умный. Продолжай.

    I’m happy to report that we at Mozilla have started working with Chromium, Edge and WebKit engineers on creating a new standard, WebAssembly, that defines a portable, size- and load-time-efficient format and execution model specifically designed to serve as a compilation target for the Web.

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

    Как только ТС уберет тег «веб» с темы, к которой он не относится =)

    P.S. черт, это еще и ты.

    Лол, убийцы яваскриптов любят сравнивать то что есть с тем чего нет.

    Я ни в коем случае не специалист, но не будет ли это жутковатым решетом?

    Всё выглядит так: из цепочки обработки asm.js выкидывают js-кодирование скомпиленной софтины, и «декодирование» оной на клиенте. Меньше кода обработки, меньше дыр, меньше трафика, меньше нагрузка на CPU/RAM.

    Когда они стали низкоуровневыми?

    Более весомые пруфы будут? Таких тикетов можно вагон найти.


    Я очень даже за LLVM в браузерах, но надо не забывать как эпично гугль профукал далвик.

    Со времён появления Явы:)

    Однажды и её назовут низкоуровневой?

    Вполне возможно когда хипстеры продавят язык программирования как в голливудских боевиках — с сиськами, 3Д и виртуальной реальностью, то и Яву начнут называть низкоуровневой:)

    О боги, кажется это уже начало конца https://2ch.hk/pr/res/494718.html

    Так то серверсайд, а это клиентсайд. Разницу чувствуешь?

    Однажды и её назовут низкоуровневой?

    Язык java под jvm уже выглядит низкоуровневым на фоне scala.

    Когда rust расправил крылья.

    В наше время пользователю проще и удобнее работать в браузере, чем качать клиент везде, где он может пригодиться.

    Вот это дырища будет.

    Но вообще непонятно, чем это отличается от всяких плагинов. Тем что не надо будет устанавливать, а эксплоит будет запускаться сам?

    Потомки, как вы там? Высадились на Марс?

    А теперь, будь добр, дай мне это развидеть!

    Какие ещё пруфы нужны? Выше по ссылке в блоге Mozilla (а так же в блогах каждого из участников) заявлено, что это совместная работа Google, Mozilla и Microsoft.

    Можно почитать твиты тех, у кого нет блогов: https://twitter.com/jfbastien/

    А можно узнать кто такой @jfbastien и его последнее место работы:

    Occupation
    Systems & Compilers Maven

    Google
    Sr. Software Engineer, 2012 — present
    Compiler engineer on Portable Native Client, currently focusing on performance and security as well as LLVM for portability. I bring portable, fast and secure native code to the Web. Side-project: tune the V8 JavaScript engine on ARM.

    Но зачем оно, если есть asm.js? Или у Гугл синдром NIH достаточной силы?

    Так это и есть js-style 🙂

    Это следующая ветвь эволюции asm.js. Не NIH, Mozilla ведь тоже причастна.

    У асмжээса размер конский получится, и набор фич от синтаксиса зависит, а не от потребностей.

    Им дали Java, но нет! Не хотят писать апплеты на Java! Хотят жрать говно!

    Уж поумнее тех мудаков, которые WebAssembly придумали.

    Всё это можно уже очень много лет как делать на Java.

    Это следующая ветвь эволюции asm.js

    Я пока не понял, в чем эволюция. Этот WebAssembly всё равно будут переводить в asm.js.

    Не NIH, Mozilla ведь тоже причастна.

    У Мозиллы нет NIH, у Гугла — есть.

    Как говоришь мне из сервлета DOM’ом манипулировать? А линковать либу на Java из JavaScript не напомнишь как?

    There are two main benefits WebAssembly provides:

    • The kind of binary format being considered for WebAssembly can be natively decoded much faster than JS can be parsed (experiments show more than 20× faster). On mobile, large compiled codes can easily take 20–40s just to parse, so native decoding (especially when combined with other techniques like streaming for better-than-gzip compression) is critical to providing a good cold-load user experience.
    • By avoiding the simultaneous asm.js constraints of (1) AOT-compilability and (2) good performance even on engines without specific asm.js optimizations, a new standard makes it much easier to add the features required to reach native levels of performance.

    WebAssembly, “wasm” for short, .wasm filename suffix, a new binary syntax for low-level safe code, initially co-expressive with asm.js, but in the long run able to diverge from JS’s semantics, in order to best serve as common object-level format for multiple source-level programming languages.

    asm.js is great, but once engines optimize for it, the parser becomes the hot spot — very hot on mobile devices. Transport compression is required and saves bandwidth, but decompression before parsing hurts. A secondary consideration: JS has a few awkward corners even in its asm.js subset. Finally, once browsers support the WebAssembly syntax natively, JS and wasm can diverge, without introducing unsafe or inappropriate features into JS just for use by compilers sourcing a few radically different programming languages.

    Вот именно, что «initially co-expressive with asm.js». Что будет потом — ТНБ знает, а пока это бинарная кодировка asm.js.

    Сейчас браузер исполняет JS, с этой хренью он точно так же будет исполнять бинарник. Права те же. Ничего не меняется.

    меняется то, что пользователь не может понять содержимое программы. Никто не может, даже Анатолий Вассерман. Это ограничивает Основную Свободу — пользователь должен четко понимать, что происходит на его компьютере.

    Некоторое время веб был оплотом Свободы потому, что всем приходилось писать на умопостижимом JS, совершенно у всех были исходники всего. Сейчас мы возвращаемся к тёмым векам, примерно как в эпоху расцвета коммерческого ПО на десктопах. С этим нужно бороться!

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

    Ну если будет polyfill в asm.js, то понятно, но они планируют что когда-то не будет? Вон Google до сих пор Dart VM не пропихнула, владея лидирующим в мире браузером, а у них точно получится

    Всё выглядит так: из цепочки обработки asm.js выкидывают js-кодирование скомпиленной софтины

    Я так понимаю asm.js код начинается с определенного комментария-директивы, что позволяет не задействовать полноценный парсер JS, а использовать специализированный, который понимает только подмножество JS — asm.js

    Все зависит от того, будет нативная поддержка где-то кроме мозиллы или нет.

    asm.js из-за этого не взлетел (и не взлетит). Поэтому рассматривать WA как бинарную упаковку asm.js не корректно. Это все-таки больше LLVM, но в первой реализации обкоцанный.

    настала пора писать заглушки «этот сайт открывается только в Mozilla Firefox, скачать его можно по ссылке» :)))

    SavePearlHarbor

    Ещё одна копия хабора

    Раскрываем тему WebAssembly с Бренданом Айком

    (Прим. перев.: технологии asm.js и WebAssembly ещё не вышли в практическую плоскость, о них регулярно идут сдержанные сигналы с самых верхов Олимпа разработки веб-технологий (Mozilla, Microsoft, Google), но многие об их состоянии знают мало. Значит, самое время — узнать о них сейчас.

    Представлено интервью Брендана Айка, сделанного 31 марта 2020 года Оно — на 1.5 часа, но 2-я половина — про проект Brave, не относится к компиляторам JS, поэтому опущена), создателя Javascript и журналистов из SE Daily (у них убедительно поясняется, почему полезно слушать такие подкасты — на сайте есть много интересного). Мы сами знаем, что рассказов о сложных идеях на уровне «слушания в автобусе» — очень мало. Текст — понятный, конечно, для программистов. Интервьюировал Caleb Meredith (CM), а редактор сайта Jeff Meyerson (JM) в основном, рекламу вставлял (её перевод опущен).

    Айка всегда было крайне трудно переводить из-за некоторых оборотов речи, поэтому есть сложные места, например, высказывания про Python, к достаточно вольному переводу которых прошу отнестись с пониманием и предлагать в таких местах варианты. Но не взяться за него, за случай, когда он говорит для людей почти (часто путая их с программистами), а не для учёных, было бы непростительно: ) )

    [0:02:53.9] CM: Я здесь [в чате?] — с Бренданом Айком, создателем языка программирования JavaScript и исполнительным директором Brave Software. Брендан, добро пожаловать в Software Engineering Daily!

    [0:03:01.0] Brendan Eich (BE): Привет, спасибо, что пригласил меня.

    [0:03:02.0] CM: Давайте начнём рзговор с WebAssembly. Самый низкоуровневый человекочитаемый формат команд, который мы предоставляем машине — это язык ассемблера, формат которого зависит от вычислительной машины. JavaScript — язык программирования гораздо более высокого уровня, но он временами описывается как язык ассемблера для Web. Недавно W3C Community Group, к которой вы, Брендан, подключились, работает над спецификацией WebAssembly. Почему полезен язык ассемблера для Web, и почему в качестве языка WebAssembly недостаточно просто JavaScript?

    Как появился и чем стал Javascript?

    [0:03:37.5] BE: Давайте, прежде всего, я начну с того, как JavaScript появился, чтобы начать играть современную роль. JavaScript я делал в спешке, в мае 1995 года в течение 10 дней, в Netscape, и он был частично ориентирован на сходство с Java, из-за внутренней политики компании. В результате, JavaScript, оттого что он загружается из HTML и может быть написан кем угодно, начиная с небольших скриптов и заканчивая большими программами, за последние 22 года занял место побежденной Java на стороне клиента в Интернете.

    JavaScript был срочной работой. Конструкции скелета, заимствованные из других языков, спешно собирались мной в теле Франкенштейна. При этом, он вышел достаточно рано не только из-за политики Netscape, но и из-за привязки Microsoft Windows к Internet Explorer и связи его с Netscape; в итоге, это привело судебному иску в США к Microsoft за злоупотребление монополией… Мы знали, что нам нужно идти быстро. У нас были кое-какие технологии в Netscape 2, такие как JavaScript, ориентированный на Java, появились новшества в HTML того времени в Netscape. Мы понимали, что если сделаем их достаточно рано, они станут частью веб-стандартов.

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

    Представьте: будучи разработчиком ПО в 90-е годы вы могли, возможно, программировать для Windows PC. Вы должны были использовать Microsoft Visual C++. Если нужна была база данных, использовалась Rogue Wave [0:05:23.4] или что-то подобное. Потом вы смОтрите в Интернет, и с удивлением видите, что там никто этого не делает. Все делают веб-сайты, не требующие инсталляции.

    Разработчики игр всё ещё использовали C++, потому что им нужно было добраться до «железа». Справедливости ради, я преувеличил, когда сказал, что никто этого не делает. Есть ещё другие «толстые» приложения, которых становилось всё меньше, потому что браузер поглотил большинство из них и превратил в серверные и базируемые на серверах модели бизнеса в ПО.

    Тем не менее, игры и ваши другие хардкорные, привязанные к «железу» приложения, если они были вынуждены использовать JavaScript — то имели проблемы, потому что JavaScript, помимо того, что он ускоренно развивался, последние 20 лет улучшались стандарты. Стало лучше. Он стал больше. Возможности возросли и сгладили некоторые неудобные места, и всё пошло хорошо, кроме сборщика мусора. Он имеет неопределённость в производительности. Предсказуемость производительности — это один из способов сказать, где вы можете рассчитать что-то на 60 кадров в секунду для игры; и вдруг — у вас заканчивается реальное время из-за сбора мусора, который должен произойти, чтобы вернуть занятую память. Или вы сделали новейший движок, и ваша программа изменила представление о типах, которые она поддерживала в интерпретаторе Javascript.
    Теперь весь код должен перекомпилироваться. Это может занять много реального времени, и вы не уложитесь в ваш 162-й кадр анимации, вас вытолкнет из этого условного предела в реальном времени. Затем игра становится медленнее, отстаёт, или анимация не обновляется должным образом. Это серёзный конкурентный недостаток для игр, поэтому разработчики предпочитают оставаться на C или C++, поэтому им нравится работать рядом с «железом».

    Компилируемое подмножество Javascript asm.js

    И вот что мы обнаружили в результате того, что JavaScript стал настолько повсеместным и быстрым, не считая этих непредсказуемых провалов производительности — мы обнаружили, что если вы используете подмножество JavaScript — это было в Mozilla, начиная с 2012 года — если вы сосредоточитесь только на частях JavaScript, которые выглядели как язык программирования C, наподобие функций редактирования для WebGL, и использовалась память в плоском большом непрерывном массиве под названием Typed Arrays — тогда, если используется подмножество JavaScript в этой модели памяти, можно работать почти так же быстро, как в C или C++. Можно выполнять программу так же, как при любом безопасном подходе к подобным низкоуровневым языкам. В этом деле были предшественники, начиная с 90-х годов; никто не слышал о них, особенно о мобильном нативном клиенте, работающем в Google, который был в то время, в 2012 году.

    Мы разработали в Mozilla это подмножество JavaScript, назвали его asm.js в честь ассемблера, сделали для него систему типов — это сделал Дейв Герман. Люк Вагнер (Luke Wagner) из Mozilla, который всё ещё там, сделал потрясающий компилятор для подмножества JavaScript с проверкой типов, такой, что за время парсинга определялось, из подмножества ли asm.js этот код, и можно было очень быстро генерировать действительно хороший машинный код, с безопасным доступом к памяти. Это было важнейшим требованием.

    Когда мы работали с Mozilla, то использовали в том числе компилятор, разработанный Алон Закай. Он написал свой Emscripten как компилятор C или C++ на основе LLVM, который генерирует JavaScript. Сказать по правде, asm.js был формализован с типизацией Дэйвом Херманом, в одиночку на самом деле — помнится, он это говорил в 2011 году на JSConf EU. Алон уже разработал интуитивное понимание подмножества в системе типов для ассемблерного JavaScript путём создания компилятора Emscripten и создания его JavaScript для быстрого перехода к JavaScript с типизированными массивами в плоской области памяти для обычных переменных в куче (heap) вместе с глобальными (куча — термин из теории компиляторов).

    Стек JavaScript использовался для переменных стека в C. Трансляция была очень аккуратной для оптимизирующих компиляторов, и только он один помог нам понять, что такое asm.js. Опять же, были предшественники. В Adobe Labs был кто-то, кто создал систему — кажется, что она называлась Alchemy — которая использовала более раннюю версию прошивки компилятора LLVM, чтобы делать то же, что ActionScript 3 в Flash Player. Мы были в курсе этой работы, и именно в этой школе мы изучали безопасные методы выполнения собственного кода.

    Тогда мы осознали, что asm.js может быть просто подмножеством JavaScript с расширением Typed Array. Он стал стандартизированным, поскольку WebGL, наконец, попал во все LSS, включая iOS. Мы поняли: «Это, вероятно, будет новая безопасная переносимая среда выполнения нативного кода. Это убьёт портативный Native Client (NaCl) в Google». Планктон в Google (the pinochle people) не хотел признавать этого, но мы действительно это сделали. Люк Вагнер написал свой быстрый компилятор. Alon Zakai продолжал работать над своим внешним интерфейсом Emscripten, который сгенерировал код JavaScript. Дэйв Херман убедился, что система типов «задышала».

    Хождение в игровой мир

    К концу 2012 года мы связались с Epic Games, разработчиком Unreal Engine, посетили небольшую группу. Менее чем за неделю, в течение четырех дней, на пятый, когда они отдыхали, Unreal Engine 3 был перенесён в веб путем кросс-компиляции своей базы кода C++, многомиллионной базы строк кода в программы JavaScript и asm.js. Надо было сделать нечто похожее на их аудио API-интерфейсы для веб-аудиоинтерфейса, и у них были адаптеры для OpenAL и других аудио-библиотек, что было несложно.

    Они уже использовали OpenGL для оптимизации графического интерфейса мобильного GPU. WebGL основан на OpenGL, так что это была быстрая адаптация. Они сделали правку бага Emscripten или две, они должны были исправить JIT-компиляцию на бекенде, которая работает на всём модуле asm.js, поэтому, в каком-то смысле, сделанное опередило время. В те выходные у них был Unreal Engine 3 с полной частотой кадров в прототипной версии Firefox. Тим Суини, основатель Epic, был ошеломлён. Он сказал: «Я думал, что на это уйдут годы. И вдруг — всё готово!».

    С того времени мы в Mozilla продолжили работать над своим движком, убедившись, что он работает для других игр. Мы работали с Unity-разработчиками. Думаю, они объявили об этом в следующем году. Мы дали знать Microsoft — они заинтересовались, поэтому я предложил поговорить в Microsoft с инженерами. После этого я встретился с Андерсом Хейлсбергом, создателем .NET и C#, и Стивом Лукко, когда тот возглавлял группу разработчиков JavaScript, команду ChakraCore в Microsoft. Они очень заинтересовались асмом и подключились к проекту на той встрече, и довольно скоро объявили об этом.

    Со временем, примерно последние три года, asm.js стали той средой, которую с неизбежностью можно было сделать сверхбыстрой. Среда выполнения, которая у вас уже есть — браузер, вместо того, чтобы пытаться добавить другую среду выполнения, — это не только переносимый собственный клиент. Хотели сделать на Dart, но это в значительной степени не удалось даже у Chrome. Очень сложно добавить вторую среду после JavaScript. Я могу понять, почему. Даже Flash, который был второй средой в качестве плагина, замедлял своё выполнение. Стив Джобс запретил его в iOS, и поэтому, я думаю, он был отозван и в Android примерно в 2011 году.

    В распоряжении не было ничего другого, кроме браузера, если нужно было иметь быструю оптимизацию для языков. Единственная проблема была в том, что все говорили, что понимают только JavaScript. Теперь был ещё asm.js — подмножество, которое могло использоваться как целевой язык для компиляторов. За последние шесть лет люди уже строили сотни компиляторов из разных языков, таких как Python, Java или Ruby — в JavaScript. Это была расхожая тема на конференциях. Люди знали, что Emscripten является одним из многих среди большого набора компиляторов.

    Над некоторыми из этих компиляторов не приходилось усиленно трудиться, чтобы оптимизировать, потому что они брали язык, который был не особо быстрым и переводили его на JavaScript. Они часто переводили языки, которые имели сходный с JavaScript семантический уровень и стиль, поэтому компилировать было легко. Это стало известно как transpiling (кросс-компиляция). Это сделано даже для наших будущих версий JavaScript и для предыдущих. Emscripten был тем, кто довёл эти вещи до машинного кода и стал использоваться разработчиками игр. Особенно, когда Unity 5 получила свою «цепочку инструментов» (tool chain), когда можно взять любую игру Unity, ткнуть кнопку, и рождалось то, что у них называется «WebGL-портом», что на самом деле означало asm.js, WebGL, веб-аудио, которые можно встроить В HTML. Просто подумайте, что у вас может быть игра для Xbox, вы ей делаете вторую жизнь в Интернете, помещаете в магазин, где её можно попробовать, прежде чем купить, просто загрузив в свой браузер. Это — большой успех.

    Как сформировалась концепция WebAssembly?

    Было ясно, что JavaScript может быть виртуальной машиной, или виртуальная машина для JavaScript может быть виртуальной машиной для мобильных языков. JavaScript по-прежнему загружается в виде исходного кода, даже в виде кода asm.js. Когда я разрабатывал JavaScript, я не выбирал кратчайшее ключевое слово для function, это восемь букв. Они — всего лишь затраты на разбор JavaScript. Даже если вы сжимаете его при транспортировке и передаете сжатие транспортного уровня, что экономит пропускную способность сети, экономит стоимость данных, а потом всё равно придётся распаковать её в памяти на целевом устройстве, а затем проанализировать.

    Оказывается, именно поэтому есть портированная Unity-игра или даже игры, в которые можно играть уже сейчас. Например игра «Ski Safari» обрела вторую жизнь на Facebook в виде скомпилированной игры asm.js; можно пойти туда и поиграть. Это очень весело. Первоначально это была мобильная игра. По-моему, она использует Unity в варианте 2D. У неё есть третье измерение, она — забавная скоростная игра катания на лыжах. Она работает на полной частоте кадров, но во время загрузки немного тормозит.

    Он работает лучше всего в Firefox из-за большой работы Люка Вагнера. Команда VA из Google не очень хотела делать ту же полную компиляцию программ, что и Люк. Люди Microsoft сделали. Они фактически взяли код Люка и изменили стиль, но сохранили авторское право за Mozilla, и его нужно было лицензировать; лицензию они использовать могли, поэтому вы, действительно, найдёте код в ChakraCore на GitHub. Этот движок теперь в Edge и в IE, вы найдете версию компилятора OdinMonkey от Люка для asm.js. Вот почему некоторые браузеры лучше других в «Ski Safari», но время загрузки — головная боль.

    Если игры сменяют уровни — там такая же проблема [скорость загрузки]. Ещё до моего ухода из Mozilla в 2014 году, мы думали: «Как это исправить? Может быть, придумаем бинарный синтаксис, который имеет смысл для этого подмножества asm.js?». Это блестяще — WebAssembly появился на наших глазах. Как только к нам подключилась Microsoft, в какой-то момент казалось, что всё могло быть закончено в начале 2015 года. Я не уверен, когда точно были эти слухи. В Google была «схватка» между командой VA и командой Portable Native Client, «кровь лилась рекой». Затем, в результате, команда VA выиграла. Это было, как я сказал, ясно всем. Вы не займётесь вторым безопасным исполняемым кодом. Думали — скорее, давайте возьмём движок JavaScript и дадим ему второй язык ввода — WebAssembly.

    Apple тоже — Apple никогда не объявляет свои ранние намерения, им всегда хочется контролировать свою историю на WWDC — но Apple попала на борт. Я могу сказать это сейчас, задним числом. Тогда я не хотел этого раскрывать. Люди из Hacker News поторапливали: теперь, говорят, у вас есть все четыре производителя браузеров с общей идеей WebAssembly. Некоторые из них даже говорили: «Да, asm.js — это просто подмножество JavaScript. Мы быстро достигнем результатов. Нам даже не нужно распознавать его как таковой, чтобы он был быстрым. Вы дадите нам C-подобный низкоуровневый JavaScript, который использует большой типизированный массив памяти. Мы будем писать быстрый код. Не волнуйтесь об этом.»

    Asm.js стал наподобие такого мальчика для битья на тему «почему у вас нет правильного двоичного синтаксиса?» И это — всего лишь один довод, убедительный аргумент в пользу WebAssembly. Как только все производители браузеров собрались в команду, WebAssembly стал продвигаться как проект сообщества W3C, как вы упомянули, и, конечно, на GitHub, где находятся код и проектные спецификации.

    Что такое WebAssembly?

    [0:19:52.7] CM: Объясните на пальцах — что такое WebAssembly? Как он выглядит? Вы открываете файл WebAssembly, что там?

    [0:19:57.8] BE: Надеюсь, я смогу рассказать — почему это полезно и почему его стали делать. Полезно — потому что он загружается быстрее и даёт вам низкоуровневую модель памяти и инструкции ради производительности. Вы можете сделать 60-кадровый шутер (стрелялку) от первого лица.

    Что это значит? Если вы думаете о JavaScript, на секунду, как о языке C, его грамматике выражений, то Си имеет все побитовые логические и сдвиговые операторы, у него есть несколько перепутанных приоритетов из-за истории языка C, и он имеет арифметические операторы. JavaScript не имеет целочисленных типов явно, но побитовыми операторами можно привести число к целочисленному 32-битовому значению, убрать знак у целых чисел со знаком во временных рядах, в оценке выражения. Это — ключ к asm.js. Так, asm.js может иметь целые числа, которые быстрее проходят через блок с плавающей запятой, не превращаясь в числа с двойной точностью IEEE 754, из-за которых все любят обвинять и JavaScript, и Java. Они были проблемой с типами JavaScript, поскольку у него только этот тип числа, поэтому люди иногда хотят использовать другой тип — а его просто ещё нет. Мы работаем над исправлением ситуации.

    В любом языке числа имеют двойную двоичную точность IEEE 754. Если вы добавите 0.1, плюс 0.2, и с полной точностью распечатаете результаты, обнаружится, что это не 0.3, а 0.300000000000000008. Это потому, что вы на самом деле делаете математику в двоично-десятичном значении, и вам нужна дополнительная точность, чтобы вычислить, как округлять, но округление выполняется с ошибкой из-за конечной точности, и в итоге получается 8 в конце после многих Нулей. Это IEEE 754.

    JavaScript-операторы побитового логического сдвига дают возможность обрабатывать 32-битные знаковые и беззнаковые целые числа, если вы используете эти операторы, как если бы они были типизированными. Для компилятора Emscripten это легко сделать, поэтому это часть волшебства, созданного Алоном Закаи, которое привело к формализованному asm.js, чтобы сделать очень быструю целочисленную математику в подмножестве JavaScript.

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

    Для более крупных структур программ есть управляющие структуры в программировании вида if-then-else, while-циклы и другие виды циклов. Очевидно, что JavaScript такие имеет. У WebAssembly они тоже есть в структурированной форме. Когда была разработана Java, она компилировалась в байт-код, а затем код отправлялся по сети. Проблема была в том, что можно было заставить какой-то ненадежный модуль послать вам плохие Java-байт-коды. Нужно было запускать так называемый верификатор.

    После весьма долгого времени, когда отсутствовала информации о типе, они, наконец, сообщили, что проверка может иметь патологическое (разрушительное) поведение. Помню, мой друг Майкл Франц, профессор в UC Irvine, показал, что у них есть алгоритм порядка 4-й степени сложности, если вы отправите этот сложный тест, что-то наподобие байт-кода верификатора, это займёт неожиданно много времени. И на верификаторы можно совершать атаки типа отказа в обслуживании (DoS).

    С WebAssembly мы узнали, что двоичный синтаксис WebAssembly, несмотря на то, что это — сочетание префикса и постфикса для части выражения, машинного кода SAC — это своего рода самопроверка в том смысле, что если вы его проанализируете, то это не сделает что-нибудь сумасшедшее [по затратам ресурсов]. Вы не проверяете код на предмет мошенничества. Поскольку верификатор пытался проверить, что это не вредоносный байт-код, который мог спутать тип в if-then-else-конструкции, вы отправляете значение через память, через переменную одного типа, и тут возможна атака, используя bad type pond или другой тип, а затем после if-then-else значения используются, но с неправильным предположением, что имеют только один тип.

    Эта проверка важна для безопасности. С помощью WebAssembly у вас нет такой неприятной проблемы анализа потока управления, которую байт-код Java имел очень долгое время, где вы можете иметь путаницу типов, если не будете тщательно анализировать операции спагетти go-to, которые возможны в байт-коде Java.

    Насколько я знаю, в WebAssembly нет никакого свободного go-to. Они немного изменили это, но я думаю, что это всё ещё структурированный код в старом смысле структурированного программирования 70-х годов. Не иметь go-to — считается вредным, т.к. с ним получается более сжатый код. Он загружается быстрее, разбирается быстрее, потребляет меньше энергии. И тогда игры, в которые вы играете, такие как Ski Safari, могут стать намного быстрее при компиляции в WebAssembly вместо asm.js.

    Какие программы сейчас можно портировать на Javascript?

    [0:24:37.8] CM: Это хорошо подходит к следующему вопросу. Вы много говорили о компьютерных играх. Честно говоря, большинство презентаций WebAssembly также демонстрируют некоторую видеоигру, запускаемую на C++ и скомпилированную с помощью WebAssembly. Каковы некоторые случаи для WebAssembly, помимо включения в игру насыщенных графикой видеоигр, или это единственный прецедент, и этот случай использования просто невероятно привлекателен с ростом WebVR или по каким-то другим причинам?

    [0:25:05.1] BE: Думаю, что описанный пример — хороший момент, но это не единственный случай использования сложных конструкций (long shot). Во-первых, игры очень сложны. Я ходил на конференцию разработчиков игр. Помнится, слышал от одного из руководителей Valve — он подчеркнул, что игры заняли место практических системных исследований в операционных системах. Они вошли в GPU, когда еще можно было управлять GPU не вредоносным кодом, пока мы находимся в песочнице [и имеем] разные потоки исполнения. Они используют многоядерность. Они перешли к блокам векторной обработки, так называемым модулям SIMD, единым командам с несколькими единицами данных, которые сейчас используются почти во всех аппаратно-программных модулях компании.

    Игры — действительно, использовали всё; Они используют потоки. Они занимались DSP. Они занимаются физикой — это не рендеринг, но всё равно, требуется много вычислений. Они используют функции ИИ — про ИИ теперь говорят на каждом углу.

    WebAssembly хорош для всех этих случаев. Он хорош для машинного обучения, алгоритмов на вашем устройстве, что бывает весьма практично. Им не нужно быть в облаке и использовать суперкомпьютеры. Они могут иногда очень эффективно выполнять более простые алгоритмы на ваших локальных данных. Это было интересно и для проекта Brave — люди нуждаются в AI (ИИ) не только для игр, но и для всех вещей сейчас, для помощи и утилит, для озвучивания текстов и наоборот.

    WebAssembly подходит для всех этих интенсивных вычислений. Игры великолепны, потому что они забавны для демо и для их зрителей. Как я уже говорил, они действительно задействуют всё это вместе. Единственное — мы не умеем делать пикселизацию, это — динамическая загруженность JavaScript. Люди думают: «О, WebAssembly! Это значит, что можно избавиться от JavaScript!». Ну, пока нет. WebAssembly запускается в виде JS с фиксированным объемом памяти для C и C++, и в планах есть сборка мусора, что должно быть сделано в интеграции со сборщиком мусора единственной рабочей среды — движка JavaScript.

    В противном случае, вы столкнётесь с проблемой коллектора циклов гостевого хоста, где в любое время, когда у вас есть две системы сбора мусора, которые могут вместе формировать ссылки в кучах, они смогут формировать циклические ссылки. Если сборщики мусора не имеют специальных протоколов для общения друг с другом, или нет главного исполнителя (supercaller), эти циклы становятся неприемлемыми. Это — аргумент в пользу того, что имеет .NET, который является многоязычным, полиглотом, виртуальной машиной с одним менеджером памяти. Это — то, во что JavaScript вырастает сейчас, улучшается поддержка многоязычности для сборки.

    WebAssembly в текущем минимально жизнеспособном продукте (MVP, minimum viable product) действительно, отражает то, что является большим достижением для C и C++ и, возможно, некоторых других языков, которые могут соответствовать модели [сборки мусора]. Со временем нужно добавить сборку мусора в этом консолидированном виде, чтобы каждый использовал GC (Garbage Collector) и Java Search Engine, не запуская гостевой GC и/или код сборки. Вы, конечно, можете это сделать когда угодно, но если когда-нибудь создадите ссылки, у вас будут неустранимые циклы.

    Хочется, чтобы динамические языки быстро, динамически выполняли метод, который может быть, а может не быть в объекте. Как и в случае с движком JavaScript на Python, иногда нет системы типов, нет стабильного представления в коде, что означает тип объекта, и вы вызываете его метод. Вы всё время вызываете один и тот же метод в одной и той же конфигурации вызова. Именно так тестируются JIT-компиляторы. Тем не менее, WebAssembly пока не имеет соответствующих инструкций. Даже гуру JavaVM вызывают методы динамически, если знают, что делает инструкция в байт-коде Java.

    Думаю, это можно поставить в планы (roadmap), ​​и это будет, но в конце. Вначале нужны несколько вещей, чтобы действительно поддерживать действительно динамические нетипизированные языки, а также статически типизированные языки: C, C++, Rust от Mozilla и других компаний, которые, как мне кажется, будут хорошо работать с WebAssembly в качестве целевого языка компилятора сейчас или в ближайшем будущем. Это значит, что нельзя быстро избавиться от JavaScript. На самом деле, JS будет таким обязательным надолго. Нет никакого определенного графика, когда вы сможете сказать: «О, да. К четвертому кварталу 2020 года мы освободимся от JavaScript и будем иметь механизм WebAssembly, и все JavaScript в Web могут быть скомпилированы браузером в WebAssembly.» Это — сомнительный план. Такого плана пока нет. Мы будем развиваться в течение многих лет и думать, что это может случиться, но когда-то потом, за горизонтом.

    Все кошки попадут в рай?

    [0:29:30.7] CM: Верно, что код будет компилироваться в WebAssembly, который со временем получит доступ ко всем API-интерфейсам браузера, к которым имеет доступ JavaScript? И однажды вы сможете написать целое приложение на языке, отличном от JavaScript, который компилируется в WebAssembly?

    [0:29:44.8] BE: думаю, что, в принципе, ответ — да. API-интерфейсы, к которым может обращаться JavaScript, должны быть доступны через WebAssembly. Вы можете сделать это любым способом, так как WebAssembly предназначен для работы в модуле, входящем в JavaScript, в ECMAScript 2015 или так называемый ES6. Мы по-прежнему имеем то, что модули работают в браузерах как отдельные спецификации рабочей группы. Это требует времени, но идея WebAssembly является модульной. Это означает, что у вас будет нечто,… как я уже говорил, у вас может быть приложение JavaScript, которое начнёт использовать модуль WebAssembly для машинного обучения или для физического движка, или временами — для интенсивных численных расчётов. Код алгоритмов для WebAssembly можно сразу писать на C или C++.

    У вас будет модель «mix-and-match» для JavaScript в WebAssembly, поэтому всегда можно отсортировать прокси-API-вызовы, которые JavaScript может сделать с кодом WebAssembly. В группе разработки WebAssembly есть хорошие мозги, которое собраны от четырёх поставщиков браузеров и понимают, как сделать вызовы API легко, безопасно и эффективно через WebAssembly.

    Я думаю, что общий ответ — да, вы получите все эти API-интерфейсы, и, конечно же, вы можете пожелать, чтобы игры были кросс-компилированы и полностью переведены на целевой язык. Сегодня это может быть asm.js, потому что WebAssemblies были только что внедрены в некоторые топовые браузеры.

    Через год [будут скомпилированы] такие игры, как Ski Safari на Facebook, Heroes of Paragon. Это те игры, которые я играл в Facebook, скомпилированные в asm.js, они могут быть скомпилированы в WebAssembly. Когда они, в значительной степени, цельные программы — вы сможете делать модули, смешивать и объединять, делая единую программу.

    По Сеньке ли шапка?

    [0:31:31.9] CM: В мире, где разработчик может написать всю программу на любом языке, который компилируется в WebAssembly, язык JavaScript должен показать, что он на самом деле — хороший язык программирования. В конце концов, разработчик может написать своё приложение в Rust или Haskell или на неизвестном будущем языке, без связи с JavaScript. Как создатель JavaScript, я хотел бы спросить: почему кто-то сознательно решил написать своё веб-приложение на JavaScript? Есть ли какая-то заслуга JavaScript, помимо того факта, что это — часть эволюционной системы, и у неё есть доля, которую она имеет сегодня, потому что он — единственный динамический язык в браузере?

    [0:32:09.4] BE: думаю, что мнения различаются по языкам. Вы заходите на Hacker News и по-прежнему видите, как люди тратят время на споры [о языках] [0:32:15.4 globs].

    [0:32:16.9] CM: Я действительно хочу услышать ваше мнение.

    [0:32:19.9] BE: Я выскажу его. На взгляд Пола Грэма — люди просто влюбляются в один язык, который они изучили первым, или они думают, что он лучше, и они безотчётно это утверждают. Я не собираюсь делать это для JavaScript. Я использую много языков. У JavaScript есть достоинства помимо того, что он вездесущ, благодаря достаточно раннему появлению из-за той грязной работы в мае 1995 года, что я делал, но JavaScript развился, и развитие было важно.

    Вы слышите, в понедельник утром, сидя в рабочем кресле, протесты в год 22-летия: «О, это мог быть Питон». Нет, этого не могло быть, потому что Python был заморожен, погас, как летающая искорка в 1995 году. Python тогда был версии 1.3. Вы бы его не хотели.

    Кроме того, Python имел небезопасный внешний интерфейс. Он по-прежнему такой же. Вы не хотели бы, чтоб он находился в Интернете, потому что это было бы подмножество Python. Затем, если он был заморожен, а внедрение JavaScript было бы слишком долгим, и прошли бы все процессы стандартизации [Пайтона], но затем у нас должен быть Firefox, чтобы перезапустить рынок браузеров; У вас была бы эволюция Python по другой линии. Это был бы Web Python. Он был бы очень старым, устаревшим. Люди проклинали бы его за то, что им не хватало одного Python 2, и тогда он попытался бы развиться, но пришлось бы развиваться иначе, потому что Web — это другая среда.

    Эволюция имеет значение. Вы можете заставить динозавров жаловаться: «О, если бы уровень кислорода не понизился, и температура не упала бы, и те свободные твари не победили бы — я бы выиграл». Это звучит беспомощно (ориг. — кислый виноград).

    Я говорю, что JavaScript действительно выиграл от эволюционной ниши, в которую попал, в пространство, в огромное пространство попал, а не в нишу. Это определенно означало, что монополия вызывает недовольство людей, где JavaScript является единственным языком. Тогда, если Божьей милостью пошёл бы Python, мы бы получили эту мерцающую искорку, полурабочую версию Python, на которую люди бы ругались, а не на JavaScript.

    Другая вещь относительно JavaScript, скажу вам, состоит в том, что я смог, несмотря на торопливость и грубые ошибки, сделать некоторые вещи правильно. Он имеет least authority model — принцип минимальных привилегий. Если вы избавитесь от нескольких «бекдоров» (уязвимостей), которые довольно широки, это может быть моделью возможностей объекта. Именно это Марк Миллер в исследованиях Google с Google Caja объявил безопасную атмосферу, которая в значительной степени сводится к стандартам, поэтому вы можете — со строгим режимом и несколькими другими моментами, вы можете контролировать доверие к смешанной среде. Вы можете использовать возможности объекта, модели безопасности с вашими базовыми безопасными указателями, прокси и мембранами для регулирования авторитета [управления объектом]. Это хорошо для JavaScript. Это есть не во всех языках, и они тоже развивались вместе с Интернетом.

    Вопросы безопасности WebAssembly

    Теперь у меня есть проблема с WebAssembly, потому что он теперь находится в W3C. В W3C есть такое мышление карго-культа, которое гласит: «У вас должна быть модель безопасности на основе междоменных запросов (cross-origin request security model)». Я думаю при этом, что забыл обо всём, что это означает — CORS. Обо всём, что касается кросс-доменности. По умолчанию вы не можете загрузить WebAssembly, это плохо. Есть ещё [у них] такой рефлекс на функцию eval в JavaScript, что все что угодно — например eval или конструктор функций — что может взять строку кода и превратить его в исполняемые объекты — плохо.

    «WebAssembly должен приходить только из URL-адресов. Он никогда не должен порождаться из строк.» — я думаю, что это просто вздор. Мы постоянно составляем программы из строк. Мы делаем это различными способами в Интернете, даже если вы попытаетесь нейтрализовать eval, он возвращается. Он поднимает голову. Это очень востребовано, и безопасность — не есть «Всё — или ничего!». Это — компромисс. Вы можете ограничивать программы с использованием eval. Вы должны быть осторожны, анализируя код, который принимается как строка. Это всегда так, потому что вы используете код в качестве строки для URL-адресов.

    Думаю, в современном мире есть риски. Безопасность никогда даже не была решена, и некоторые проблемы беспокоили крупные компании типа Google. Вы получаете что-то вроде, как я уже сказал, карго-культовых ограничений типа «всё или ничего», думая о безопасности, которая на самом деле, думаю, не подходит ни для безопасности, ни для удобства. Мне не нравится старый подход к юзабилити безопасности. Думаю, что лучшие решения, которые я видел, включают оба подхода.

    В отношении безопасности языков, Rust — это язык, который имеет статическую модель безопасности. У вас не может быть нулевого указателя ссылки во время выполнения. Вы не можете иметь ошибки памяти за пределами массива в C-С++. Вы не можете расширить права в многопоточном коде, что является теоремой, легко вытекающей из прав собственности.

    Rust очень интересно компилируется в WebAssembly, и я бы выбрал его по сравнению с JavaScript всякий раз, когда делаю какой-то тяжелый машинный, но безопасный код. Да, JavaScript — не молоток для всех гвоздей. Это никогда так не было, поэтому некоторые люди будут использовать Java или Flash ActionScript, или даже компиляторы, генерирующие код ActionScript. Другие типы программ времени исполнения умерли. Они стали символами вредоносности ПО — JavaVM, JRE-плагины или Flash.

    Потому что они принадлежали одной компании, которая «потеряла нюх» (took its eye off the ball) и не обновляла установку заплаток безопасности достаточно быстро, или, если делалось, то всё равно поздно, как в случае с Flash. Стало легко заводить фермы ошибок, и плохим парням не приходилось беспокоиться о разных версиях браузера.

    Разнообразие реализаций браузеров на самом деле было препятствием для этих плохих парней. Думаю, это будет верно для WebAssembly. Для атаки будут использоваться разные механизмы, поэтому лучше иметь некоторое разнообразие в вашей системе и уровне реализации. Это более глубокий момент, который я бы отметил. По исследованию Константина Довролиса из Georgia Tech, я полагаю, что в любой сетевой системе с иерархическими стеками протоколов или языковыми стеками, или и тем и другим, как правило, получаются эти эволюционирующие структуры в виде песочных часов, где талия осы в виде горлышка песочных часов похожа на JavaScript или HTTP TCP/IP. Это становится эволюционирующим ядром, которое в интересах каждого человека быть обратно совместимым и развиваться медленно и осмотрительно, с учетом соображений безопасности. Тогда вы получите большое разнообразие выше и ниже. Как и в работе Довролиса над сетевым стеком, вы получаете множество слоёв связи от старого 10-мегабитного Ethernet на коаксиальном кабеле до Metropolitan Ethernet на fiber optic или другие коммуникации по радиосвязи через наши телефоны.

    Все слои каналов связи отличаются друг от друга и инновационны для своего времени и пространства, но все они проходят через старый протокол TCP/IP. Это тоже развивается. Мы получаем [20:38:48.5] HTTP/2 и ждём новшеств от Google. Там всегда эволюция медленная, но ведь очень сложно заменить старые протоколы. Мы по-прежнему используем DNS, систему доменных имён. Эти формы эволюционных ядер — они стабильны, они подобны по-своему ценной ДНК. То же самое касается JavaScript. Поскольку браузер выигрывает как в рантайме, так и в мобильной среде, то похоже, что это будет продолжаться некоторое время. Опять же, я не могу указать дату конца в JavaScript.

    Мир — это война (браузеров)?

    CM: Последний вопрос, и он поможет перейти к разговору о Brave. Теперь, с WebAssembly, есть ли вероятность увидеть новую эру войны браузеров, потому что все будут конкурировать за лучшую реализацию WebAssembly?

    [0:39:27.7] BE: Это хороший вопрос. Я не знаю. Браузерные войны трудно предсказать, но они действительно возникают, когда на рынке браузеров действительно что-то не в порядке, как монопольный захват рынка, случившийся в США. В самом деле, случай с игнорированием рынка со стороны Microsoft, который, как мне кажется, разжёг скандал против Microsoft в плане доверия к ней после того, как она подвергла сомнению простую мысль, что стандарты необходимы. Она ещё не была наказана в ЕС за Windows Media Player и дальнейшую монополизацию своего браузера, поэтому она не сформировала свои стандарты бюрократии и дипломатии, которые Microsoft имеет сейчас. Сейчас её стандарты — намного лучше.

    В те времена они сказали: «Вернёмся к Windows. Давайте сделаем старую добрую блокировку со стороны Windows. Мы используем .NET, потому что Ander проделал хорошую работу с C# и средой выполнения .NET. «Это подготовило почву для нового мира браузеров, который был запущен Firefox. Когда я был одним из тех людей, которые построили его, я набрал весь технический персонал и был одним из главных менеджеров проекта, когда мы вышли из AOL. Мы знали, что рынок браузеров был гибким (на него можно было пробраться), потому что Microsoft вышла из него. Они оставили IE6, как своё время, IE5, но 6-й был не лучше; ужасный браузер с архитектурой, имевшей огромные проблемы с безопасностью из-за ActiveX, и множество всплывающих окон в качестве одной из форм доставки рекламы, поэтому мы делали такие вещи, как управление всплывающими окнами.

    Браузеры становятся уязвимыми по многим причинам. Не думаю, что WebAssembly будет уязвимым, поэтому надеюсь, что все производители браузеров будут выполнять код Java WebAssembly. На самом деле, я обеспокоен тем, что после MVP — минимального жизнеспособной реализации продукта, который хорош для C и C++ или Rust или подобных языков — что производители браузеров пойдут разными путями, потому что они не могут быть дружными под давлением конкуренции; Потребуется некоторая дисциплинарная работа и хорошая социальная сеть, чтобы поддерживать WebAssembly в направлении дальнейшего следования планам после MVP, связанная с поддержкой сборки мусора, динамическими языками, которые обеспечивают быструю поддержку вызова метода, других требуемых функций.

    Может быть, они дойдут до реализации. Надеюсь, что да. Может быть, они будут двигаться медленнее. После MVP у них может быть небольшая пауза в WebAssembly, когда они освоятся, и разработчики разберутся, как лучше использовать инструменты, как делать все эти модули для машинного обучения, физики или разных численных расчётов, смешивать и конфигурировать инструменты, потому что люди теперь используют цепочки инструментов (tool chains) с JavaScript, что является большим прорывом.

    16 лет назад люди говорили: «Ура, JavaScript! Я хочу писать только нативно. Никаких уродливых инструментов!». Затем постепенно, через Lint, JSLint и ESLint, а затем и Babel ES6, люди стали использовать кросс-компиляторы, и на самом деле, было бы полезно уменьшить различия между браузерами. Поэтому, когда люди учатся, как во время разработки смешивать в WebAssembly и компилировать код из другого исходного языка, они другие языки учатся смешивать с JavaScript. Будь то всё приложение или его часть, на это умение потребуется время.

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

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

    Мастер Йода рекомендует:  Rich Internet Application и контент-менеджмент
  • Добавить комментарий