Потоки WebAssembly готовы к использованию в Chrome 70

Поддержка потоков WebAssembly появилась в Chrome 70 в рамках пробной версии.

Alex Danilo

WebAssembly (Wasm) позволяет компилировать код, написанный на C++ и других языках, для запуска в Интернете. Одной из очень полезных особенностей собственных приложений является возможность использования потоков — примитива для параллельных вычислений. Большинство разработчиков C и C++ знакомы с pthreads — стандартизированным API для управления потоками в приложении.

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

Версия Chrome 70 поддерживает потоки для WebAssembly, и мы призываем заинтересованных разработчиков начать использовать их и оставить нам отзыв.

Потоки? А как насчет рабочих?

Браузеры поддерживают параллелизм через Web Workers с 2012 года в Chrome 4; на самом деле это нормально слышать такие термины, как «в основном потоке» и т. д. Однако веб-работники не обмениваются между собой изменяемыми данными, вместо этого полагаясь на передачу сообщений для связи. Фактически, Chrome выделяет для каждого из них новый движок V8 (называемый изолятами). Изоляты не имеют совместного использования ни скомпилированного кода, ни объектов JavaScript, поэтому они не могут совместно использовать изменяемые данные, такие как pthreads.

С другой стороны, потоки WebAssembly — это потоки, которые могут использовать одну и ту же память Wasm. Базовое хранилище общей памяти осуществляется с помощью SharedArrayBuffer , примитива JavaScript, который позволяет одновременно использовать содержимое одного ArrayBuffer между рабочими процессами. Каждый поток WebAssembly выполняется в Web Worker, но их общая память Wasm позволяет им работать так же, как на собственных платформах. Это означает, что приложения, использующие потоки Wasm, отвечают за управление доступом к общей памяти, как и в любом традиционном многопоточном приложении. Существует множество существующих библиотек кода, написанных на C или C++, которые используют pthreads , и их можно скомпилировать в Wasm и запустить в истинном многопоточном режиме, позволяя большему количеству ядер одновременно работать с одними и теми же данными.

Простой пример

Вот пример простой программы на языке C, использующей потоки.

#include <pthread.h>
#include <stdio.h>

// Calculate Fibonacci numbers shared function
int fibonacci(int iterations) {
    int     val = 1;
    int     last = 0;

    if (iterations == 0) {
        return 0;
    }
    for (int i = 1; i < iterations; i++) {
        int     seq;

        seq = val + last;
        last = val;
        val = seq;
    }
    return val;
}
// Start function for the background thread
void *bg_func(void *arg) {
    int     *iter = (void *)arg;

    *iter = fibonacci(*iter);
    return arg;
}
// Foreground thread and main entry point
int main(int argc, char *argv[]) {
    int         fg_val = 54;
    int         bg_val = 42;
    pthread_t   bg_thread;

    // Create the background thread
    if (pthread_create(&bg_thread, NULL, bg_func, &bg_val)) {
        perror("Thread create failed");
        return 1;
    }
    // Calculate on the foreground thread
    fg_val = fibonacci(fg_val);
    // Wait for background thread to finish
    if (pthread_join(bg_thread, NULL)) {
        perror("Thread join failed");
        return 2;
    }
    // Show the result from background and foreground threads
    printf("Fib(42) is %d, Fib(6 * 9) is %d\n", bg_val, fg_val);

    return 0;
}

Этот код начинается с функции main() , которая объявляет две переменные fg_val и bg_val . Существует также функция fibonacci() , которая будет вызываться обоими потоками в этом примере. Функция main() создает фоновый поток с помощью pthread_create() , задача которого — вычислить значение числовой последовательности Фибоначчи, соответствующее значению переменной bg_val . Тем временем функция main() , выполняющаяся в потоке переднего плана, вычисляет ее для переменной fg_val . После завершения фонового потока результаты распечатываются.

Компилировать для поддержки потоков

Во-первых, у вас должен быть установлен emscripten SDK , желательно версии 1.38.11 или новее. Чтобы создать код нашего примера с потоками, разрешенными для работы в браузере, нам нужно передать пару дополнительных флагов компилятору emscripten emcc . Наша командная строка выглядит так:

emcc -O2 -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=2 -o test.js test.c

Аргумент командной строки ' -s USE_PTHREADS=1 ' включает поддержку потоков для скомпилированного модуля WebAssembly, а аргумент ' -s PTHREAD_POOL_SIZE=2 ' указывает компилятору создать пул из двух (2) потоков.

Когда программа запускается, она под капотом загружает модуль WebAssembly, создает веб-воркер для каждого из потоков в пуле потоков, разделяет модуль с каждым из воркеров, в данном случае это 2, и они будут использоваться. всякий раз, когда выполняется вызов pthread_create() . Каждый рабочий создает экземпляр модуля Wasm с одной и той же памятью, что позволяет им сотрудничать. Новейшие изменения V8 в версии 7.0 используют скомпилированный собственный код модулей Wasm, который передается между рабочими процессами, что позволяет даже очень большим приложениям масштабироваться для множества рабочих процессов. Обратите внимание: имеет смысл убедиться, что размер пула потоков равен максимальному количеству потоков, необходимых вашему приложению, иначе создание потока может завершиться неудачно. В то же время, если размер пула потоков слишком велик, вы будете создавать ненужные веб-воркеры, которые будут сидеть и ничего не делать, кроме использования памяти.

Как попробовать

Самый быстрый способ протестировать наш модуль WebAssembly — включить экспериментальную поддержку потоков WebAssembly в Chrome 70 и более поздних версиях. Перейдите по URL-адресу about://flags в своем браузере, как показано ниже:

Страница флагов Chrome

Затем найдите экспериментальную настройку потоков WebAssembly, которая выглядит следующим образом:

Настройка потоков WebAssembly

Измените настройку на «Включено» , как показано ниже, затем перезапустите браузер.

Настройка потоков WebAssembly включена

После перезапуска браузера мы можем попробовать загрузить поточный модуль WebAssembly с минимальной HTML-страницей, содержащей только этот контент:

<!DOCTYPE html>
<html>
  <title>Threads test</title>
  <body>
    <script src="test.js"></script>
  </body>
</html>

Чтобы попробовать эту страницу, вам нужно запустить какой-либо веб-сервер и загрузить его из браузера. Это приведет к загрузке и запуску модуля WebAssembly. Открытие DevTools показывает нам выходные данные запуска, и вы должны увидеть в консоли что-то вроде выходного изображения:

Вывод консоли из программы Фибоначчи

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

Тестирование в полевых условиях с помощью пробной версии Origin

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

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

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

Если вы хотите увидеть, что 4 потока, работающие параллельно, могут сделать с ASCII-изображениями, вам также следует взглянуть на эту демонстрацию !

Оставьте нам отзыв

Потоки WebAssembly — чрезвычайно полезный новый примитив для переноса приложений в Интернет. Теперь можно запускать приложения и библиотеки C и C++, которым требуется поддержка pthreads, в среде WebAssembly.

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