Браузерные компиляторы запускают ваш код прямо внутри веб-страницы с помощью WebAssembly: компактного бинарного формата в изолированной среде, который браузеры превращают в быстрый машинный код. Настоящие компиляторы и интерпретаторы, такие как Clang, CPython, R и SQLite, сами скомпилированы в WebAssembly, загружаются один раз, а затем компилируют или запускают вашу программу на вашем устройстве, ничего не отправляя на сервер. Традиционные онлайн-компиляторы работают наоборот: они загружают ваш код на сервер, который его выполняет и возвращает результат.
- WebAssembly — переносимая цель компиляции, которую все основные браузеры выполняют со скоростью, близкой к нативному коду, в той же песочнице безопасности, что и JavaScript.
- Наши компиляторы C и C++ запускают Clang во вкладке: он превращает ваш код в модуль WebAssembly, который затем выполняется с небольшим слоем WASI, обеспечивающим ввод и вывод.
- Python, R, SQL, Ruby, PHP, Lua и Prolog работают как сборки официальных интерпретаторов под WebAssembly; языки семейства JavaScript используют собственный движок браузера.
- Локальный запуск даёт конфиденциальность, отсутствие очереди на сервере и работу офлайн после кеширования среды выполнения.
- Расплата за это — разовая загрузка, отсутствие потоков и сетевых сокетов, временная файловая система в памяти и, в нашей сборке C++, отсутствие исключений.
Что такое WebAssembly
WebAssembly (часто сокращённо Wasm) — низкоуровневый формат инструкций, созданный как цель компиляции. Обычно его не пишут вручную. Вместо этого компилятор, например Clang или компилятор Rust, создаёт из обычного исходного кода файл .wasm — так же, как создал бы исполняемый файл для процессора x86 или ARM. Формат является открытым стандартом, который разрабатывается в W3C, описан на webassembly.org и поддерживается в Chrome, Edge, Firefox и Safari.
Три свойства делают его удобным для запуска кода в браузере:
- Переносимость. Один и тот же файл
.wasmработает в Windows, macOS, Linux, Android и iOS, на любом процессоре, потому что браузер превращает его в локальный машинный код. - Скорость. WebAssembly типизирован и близок к «железу», поэтому движки браузеров могут компилировать его заранее, до выполнения, в эффективный машинный код. Ресурсоёмкий код обычно работает намного быстрее, чем аналогичный на JavaScript, и в целом в том же диапазоне, что и нативный, хотя, как правило, чуть медленнее.
- Изоляция. Модуль WebAssembly получает блок собственной памяти и может вызывать только те функции, которые ему явно предоставили. Он не может читать ваши файлы, открывать сетевые соединения или трогать остальную страницу, если только управляющий код не даёт такой возможности.
WASI: системный интерфейс для WebAssembly
Программа на C ожидает наличия операционной системы: чего-то, откуда можно читать стандартный ввод, куда можно писать вывод, открывать файлы и узнавать время. В WebAssembly ничего этого не встроено. WebAssembly System Interface (WASI) задаёт стандартный набор таких функций, которые программа WebAssembly может импортировать. Вне браузера среды выполнения, например Wasmtime, реализуют WASI поверх настоящей операционной системы. Внутри браузера эти функции реализует небольшая JavaScript-библиотека, называемая WASI-прослойкой (WASI shim), поверх данных в памяти.
Как работают традиционные онлайн-компиляторы
Большинство давно существующих онлайн-компиляторов и сайтов с задачами по программированию запускают ваш код на своих серверах:
- Браузер отправляет исходный код (и входные данные, если они есть) на сервер сайта.
- Сервер помещает его в изолированную среду, как правило контейнер или лёгкую виртуальную машину, с ограничениями по времени, памяти и числу процессов.
- Настоящий компилятор или интерпретатор, установленный там, собирает и запускает программу.
- Вывод перехватывается и отправляется обратно в браузер, а среда уничтожается.
У такой модели есть реальные преимущества. Сервер может предложить почти любой язык и версию, полный набор возможностей операционной системы, например потоки и процессы, а иногда и доступ к сети и большие библиотеки. Но ваш код покидает устройство, загруженные сервисы могут ставить запросы в очередь, каждый запуск зависит от обращения по сети, а владельцу приходится платить за вычислительные мощности при каждом выполнении — поэтому многие ограничивают число запусков или требуют аккаунт.
Как работают наши браузерные компиляторы
В наших онлайн-компиляторах среда выполнения для каждого языка загружается в ваш браузер и запускается внутри Web Worker — фонового потока, благодаря которому страница остаётся отзывчивой, пока работает ваша программа. Ограничение по времени и кнопка «Остановить» позволяют странице завершить worker, если программа выполняется слишком долго, например из-за бесконечного цикла. Файлы среды выполнения закреплены за точными версиями, и большинство из них перед запуском проверяются по криптографическому хешу.
C и C++: настоящий компилятор во вкладке
Инструменты Онлайн-компилятор C и Онлайн-компилятор C++ используют Clang 21 — компилятор на базе LLVM, упакованный в WebAssembly проектом YoWASP. Каждый запуск проходит в два этапа:
- Компиляция. Clang, сам работающий как WebAssembly, компилирует ваш
main.cилиmain.cppс включёнными оптимизацией и предупреждениями (C17 или C++20). На выходе получается не исполняемый файл для x86 или ARM, а новый модуль WebAssembly для WASI. Предупреждения и ошибки компилятора показываются точно так, как их выводит Clang. - Запуск. Браузер компилирует этот модуль в машинный код и запускает его с WASI-прослойкой. Прослойка связывает стандартный ввод с текстом в поле ввода, а стандартный вывод и стандартный поток ошибок направляет на панель вывода.
Иными словами, компилятор, скомпилированный в WebAssembly, создаёт вашу программу, скомпилированную в WebAssembly, и обе работают в одной вкладке.
Интерпретаторы, скомпилированные в WebAssembly
| Язык | Среда выполнения | Что это |
|---|---|---|
| Python | Pyodide | CPython, эталонный интерпретатор Python, скомпилированный в WebAssembly. Для него также собраны пакеты, такие как NumPy и pandas. |
| R | webR | Официальная сборка R под WebAssembly, включая базовую графику. |
| SQL | sql.js | Движок базы данных SQLite, скомпилированный в WebAssembly; база хранится в памяти. |
| Ruby | ruby.wasm | Официальный интерпретатор CRuby, собранный для WASI, со стандартной библиотекой. |
| PHP | php-wasm | Интерпретатор PHP, скомпилированный в WebAssembly. |
| Lua | wasmoon | Эталонный интерпретатор Lua 5.4, скомпилированный в WebAssembly. |
| Prolog | swipl-wasm | SWI-Prolog, скомпилированный в WebAssembly. |
Поскольку это те же интерпретаторы, которые люди устанавливают на свои компьютеры, поведение и сообщения об ошибках близко совпадают с десктопными версиями. Попробовать их можно здесь: Онлайн-компилятор Python, Онлайн-компилятор R и Онлайн-компилятор SQL.
Языки, которые используют собственный движок браузера
Некоторым языкам WebAssembly вообще не нужен. Онлайн-компилятор JavaScript запускает код прямо в движке JavaScript браузера. TypeScript и CoffeeScript переводятся в JavaScript своими официальными компиляторами, которые распространяются в виде JavaScript, а результат затем запускается так же. Scheme использует BiwaScheme, а Clojure — SCI (Small Clojure Interpreter); оба — интерпретаторы, которые сами работают на JavaScript.
Преимущества запуска кода в браузере
- Конфиденциальность. Ваш исходный код и входные данные остаются на вашем устройстве. Они не загружаются на наш сервер, не хранятся и не записываются в журналы, потому что сервер их никогда не получает.
- Без очереди и без аккаунта. Каждый посетитель использует собственный процессор, поэтому общей очереди на выполнение нет и запуски не приходится нормировать.
- Работает офлайн после загрузки. Когда страница и среда выполнения загружены и закешированы, вы можете продолжать редактировать и запускать код при потере соединения, пока вкладка остаётся открытой. Дополнительным пакетам, которые подгружаются по требованию, например некоторым библиотекам Python, при первой загрузке всё равно нужно соединение.
- Быстрые повторные запуски. После первой загрузки интерпретируемые языки стартуют почти мгновенно, и между нажатием «Запустить» и появлением результата нет обращения по сети.
Ограничения и компромиссы
| Ограничение | Почему оно есть | Что это значит на практике |
|---|---|---|
| Размер загрузки | В браузер нужно доставить весь компилятор или интерпретатор. | Clang, R и Ruby занимают десятки мегабайт; Lua и SQLite — меньше одного. При следующих визитах используется кеш браузера. |
| Нет потоков | Наши среды выполнения однопоточные; потокам WebAssembly нужны дополнительные настройки изоляции в браузере и поддержка среды выполнения. | pthread, std::thread или threading в Python для настоящего параллелизма будут работать не так, как на десктопе. |
| Нет сетевых сокетов | Песочница не даёт программам открывать прямые сетевые соединения. | Код на C, Python или R, который открывает сокеты или делает HTTP-запросы, завершится ошибкой. JavaScript в браузере по-прежнему может использовать fetch. |
| Нет настоящей файловой системы | Среды выполнения получают в лучшем случае виртуальную файловую систему в памяти, но никогда не ваш диск. | Python и некоторые другие среды могут создавать файлы во время сеанса, но те исчезают при закрытии страницы; наши программы на C и C++ получают только стандартный ввод и вывод. |
| Нет исключений C++ | Наша сборка C++ компилируется с отключёнными исключениями (-fno-exceptions). | Код с try, catch или throw не скомпилируется; используйте возвращаемые значения или коды ошибок. |
| Память | 32-разрядный WebAssembly может адресовать не более 4 ГиБ, а браузеры или устройства могут разрешать меньше. | Очень большие массивы или наборы данных могут приводить к ошибкам нехватки памяти, особенно на телефонах. |
| Ввод не интерактивный | Стандартный ввод подаётся до запуска программы. | Сначала введите все данные в поле ввода; запросы не могут ждать вас посреди выполнения. |
Для обучения, проверки алгоритмов и учебных заданий эти ограничения редко имеют значение. Для программ, которым нужны сеть, несколько процессов или много памяти, используйте локальную установку или серверную среду.
Модель безопасности
Запуск произвольного кода звучит рискованно, но браузерные компиляторы опираются на защиту, которую браузеры и так применяют к каждому сайту.
- Изоляция WebAssembly. Модуль может читать и записывать только собственную линейную память, границы которой проверяются, и вызывать только те функции, которые ему явно импортированы. Программа на C с переполнением буфера может повредить собственную память, но не может вырваться в браузер или операционную систему.
- Песочница браузера. Весь код страницы, включая WebAssembly и Web Worker, работает внутри процессной песочницы браузера и правил одного источника (same-origin), поэтому не может читать данные других сайтов или ваши файлы.
- Worker и ограничения по времени. Запуск в worker означает, что «убежавшую» программу можно завершить, не замораживая и не перезагружая страницу.
- Проверенные среды выполнения. Закрепление точных версий и проверка хешей там, где это позволяет способ загрузки, защищают от того, что сеть доставки контента незаметно отдаст другой или изменённый файл.
Одна оговорка: JavaScript, который вы запускаете в компиляторе JavaScript, обладает теми же возможностями, что и любой скрипт на веб-странице, включая сетевые запросы. Как и с любым кодом, запускайте только те фрагменты, которые понимаете, особенно скопированные у незнакомцев.
Когда какой онлайн-компилятор выбрать
- Если ваш код конфиденциален, например учебные задания или рабочий код, выбирайте браузерный компилятор, чтобы код не покидал ваше устройство.
- Если вам нужны потоки, сокеты, определённая системная библиотека или язык без сборки под WebAssembly, используйте серверный сервис или локальную установку.
- Если у вас медленное или лимитное соединение, начните с более лёгких сред выполнения; главная цена — первая загрузка тяжёлой.
Часто задаваемые вопросы
Отправляется ли мой код на сервер, когда я пользуюсь вашими онлайн-компиляторами?
Нет. Страница загружает компилятор или интерпретатор, а ваш код и входные данные компилируются и выполняются на вашем устройстве. Сервер лишь отдаёт страницу и файлы среды выполнения.
WebAssembly так же быстр, как нативный код?
Обычно он близок по скорости, но немного медленнее; разрыв зависит от задачи и браузера. Для типичных упражнений и алгоритмов разница незаметна; большую задержку вызывает первая загрузка.
Почему первый запуск занимает больше времени?
При первом запуске загружается и инициализируется среда выполнения, а для Clang, R или Ruby это десятки мегабайт. Браузер кеширует эти файлы, поэтому при следующих визитах всё стартует намного быстрее.
Почему мой код на C++ с try и catch не компилируется?
Наша сборка C++ компилируется с отключёнными исключениями, потому что обработка исключений в WebAssembly требует дополнительной поддержки со стороны инструментария и среды выполнения, которую в этой конфигурации мы не используем. Перепишите обработку ошибок с помощью возвращаемых значений, std::optional или кодов ошибок либо компилируйте локально, если исключения вам необходимы.
Может ли программа в онлайн-компиляторе навредить моему компьютеру?
Код, выполняемый как WebAssembly в браузере, ограничен собственной памятью и функциями, которые предоставляет страница, а песочница браузера добавляет ещё один уровень защиты. Он не может читать ваши файлы или устанавливать программы. JavaScript-код по-прежнему может отправлять веб-запросы, как любой скрипт страницы, поэтому не запускайте код, которому не доверяете.
Комментарии
Войдите, чтобы оценить этот инструмент.
Поделитесь советом, задайте вопрос или расскажите, как вам помог инструмент.
Комментариев пока нет. Расскажите первым, как всё прошло.