thread-like

    1.2.4 • Public • Published

    Thread-like

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

    npm version

    Установка

    npm install thread-like
    <script src="https://cdn.jsdelivr.net/npm/thread-like/lib/parallelize.js"></script>

    Demo

    Зачем?

    Допустим, в ответ на действие пользователя нужно посчитать какой-то большой объем данных. Если этот процесс будет занимать больше 16 миллисекунд (столько нужно, чтобы хватило времени на рендер 60 кадров в секунду), пользователь может заметить задержки. При больших значениях (200+) страница и вовсе будет восприниматься, как "зависшая".

    В качестве примера можно взять такой код:

    function longBlockingOperation() {
      let count = 0;
      while (count++ < 2500) {
        doSmth(); // Какие-то операции на 0.1 – 0.5 миллисекунды
      }
    }

    Если его просто запустить, страница заблокируется примерно на секунду. Достаточно, чтобы подумать, что с сервисом что-то не так.

    Профайлер покажет примерно такой результат: на 964 миллисекунды поток выполнения заблокирован задачей longBlockingOperation.

    Профайлер при синхронном выполнении задачи

    Решение

    Пакет thread-like позволяет с минимальными изменениями кода сделать такую функцию

    • не блокирующей поток выполнения
    • прерываемой
    • выполняемой параллельно с другими подобными задачами

    Выполнение будет разбиваться на небольшие части:

    Параллельное выполнение

    Для параллельного выполнения не требуется никаких дополнительных действий. Исполнитель будет запускать части всех задач поочередно, создавая подобие параллельности: здесь задачи l1, l2 и l3 выполняются одновременно.

    API

    Создание параллельной функции (parallelize)

    import { parallelize } from "thread-like";
    
    const config = {}; // Опциональный конфиг
    
    const longNonBlockingOperation = parallelize(function* longBlockingOperation() {
      let count = 0;
      while (count++ < 2500) {
        yield doSmth();
      }
      return count;
    }, config);
    Поле конфига Тип Значение по-умолчанию
    debug boolean false
    maxTime number null
    1. Функцию нужно сделать генератором (function*, подробнее)
    2. В местах, где планировщику можно будет остановиться, чтобы дать браузеру время на рендер, нужно разместить оператор yield

    yield'ов не должно быть слишком много. Идеально, если между двумя yield будет проходить хотя бы 0.1 миллисекунды. В противном случае на переключение и контроль времени будет уходить больше ресурсов, и выполнение задачи замедлится в разы.

    Теперь вызов longNonBlockingOperation будет запускать блокирующую операцию, и приостанавливать её в yield тогда, когда время, выдаваемое на блокировку (13 миллисекунд), истекло.

    Подписка на результат выполнения (task)

    const task1 = longNonBlockingOperation();
    const task2 = await longNonBlockingOperation();

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

    Дополнительно к интерфейсу промиса, у таски будет метод abort для её остановки.

    Отмена выполнения (abort)

    task.abort(resolve);

    Остановит выполнение таски, промис перейдет в состояние fullfilled или rejected в зависимости от параметра resolve (по умолчанию true). Значением в обработчике будет символ Aborted:

    import { Aborted, isAborted } from 'thread-like';
    ...
    try {
      const task = await runTask();
    } catch (e) {
      if (!isAborted(e)) { // Или e !== Aborted
        // Обработка ошибки
      }
    }

    Helpers

    Yield каждые n итераций

    Позволяет останавливать выполнение не каждый раз, а каждые n итераций.

    import { parallelize, everyNth } from 'thread-like';
    ...
    const p = parallelize(function* () {
      let count = 0;
      while (true) {
        count++;
        yield* everyNth(count, 100);
      }
    });

    Install

    npm i thread-like

    DownloadsWeekly Downloads

    4

    Version

    1.2.4

    License

    MIT

    Unpacked Size

    846 kB

    Total Files

    40

    Last publish

    Collaborators

    • kshshe