navigator.hardwareConcurrency и планирование Web Worker
Как понимать navigator.hardwareConcurrency, выбрать размер пула Web Worker и проверять параллельность, не принимая подсказку браузера за число ядер.
Нужна структурированная документация по теме Платформа?
Эта статья относится к редакционной библиотеке. Для пошаговой настройки, справки и постоянных обновлений переходите сразу в соответствующий раздел docs.
navigator.hardwareConcurrency - это подсказка браузера о параллельности, а не обещание, что страница сможет одновременно выполнять столько задач. Используйте ее как один из входов в ограниченную политику пула Worker, а затем измеряйте ожидание в очереди, время завершения, нагрузку на память и отзывчивость. Хороший план останавливает добавление Worker до того, как они начнут в основном создавать конкуренцию за ресурсы.
Значение показывает число логических процессоров, доступных странице, и браузер может уменьшить его, ограничивая параллельность. Руководство по устройству и области просмотра показывает другую границу: значение браузерного API помогает совместимости, но не описывает устройство целиком.
Что означает это значение
Справочник MDN по Navigator.hardwareConcurrency определяет его как число логических процессоров, доступных для запуска потоков на компьютере пользователя. Там же указано, что браузер может сообщать меньшее число, чем есть у машины. Поэтому значение подходит для начальной оценки, но не доказывает количество физических ядер, текущую загрузку CPU или объем памяти страницы.
Свойство можно прочитать через navigator в окне и через глобальную область Worker. Оно не создает потоки, не резервирует время CPU и не делает задачу параллельной. Worker по-прежнему обменивается сообщениями, а страница несет затраты на сериализацию, планирование, выделение и синхронизацию.
Считайте изменения обычными событиями совместимости. Другая версия браузера, политика операционной системы, режим питания, настройка приватности или другой контекст выполнения могут показать другую подсказку. Не используйте число как сигнал личности, основание для авторизации или повод собирать более подробный аппаратный профиль.
Превращаем подсказку в политику Worker
Начните с небольшого пула и очереди. Для независимых задач, ограниченных CPU, начальный предел не должен превышать сообщенную подсказку и часто должен быть ниже. Оставьте ресурсы странице, обработке ввода, сети, отрисовке и операционной системе. Для задач, ограниченных вводом-выводом, может хватить меньшего числа Worker, потому что они ждут.
Модель Worker в WHATWG определяет Worker как отдельный контекст выполнения, который обменивается сообщениями с создателем. Поэтому очередь важна: отправляйте ограниченные партии, при необходимости передавайте большие буферы и заранее определяйте поведение при отмене задачи или сбое Worker. Пул должен уметь перестать принимать работу, а не расти бесконечно.
Используйте политику вроде min(availableHint, configuredMaximum), а не копируйте подсказку напрямую в размер пула. Задайте отдельный максимум для мобильных или ограниченных по памяти контекстов; если стоимость задачи известна, приоритет должен быть у лимита приложения. Настроенный максимум - решение продукта, а подсказка браузера - только входной параметр.
Измеряем насыщение и отзывчивость
Тестируйте настоящую задачу, а не пустой цикл. Записывайте ожидание в очереди, время выполнения, сквозное завершение, сбои и отмены, использование памяти и отзывчивость главного потока. На репрезентативных данных сравните один Worker, небольшой пул и большие пулы. Прекратите наращивать параллельность, когда пропускная способность перестает расти или ухудшаются задержка, память и взаимодействие.
Разделяйте холодные и теплые прогоны. Запуск Worker и загрузка скрипта могут доминировать в короткой задаче, а длинный поток может упираться в вычисления или передачу сообщений. Фиксируйте версию браузера, размер входа, класс устройства и состояние питания, чтобы сравнение оставалось воспроизводимым. Не выводите физическую топологию машины только из времени выполнения.
Проверяйте и отказы. Завершенный Worker, отклоненное сообщение, нехватка памяти или изменение видимости страницы должны вернуть работу в ограниченную очередь либо привести к понятному состоянию ошибки. Отмена должна освобождать буферы и удалять задачу из учета. Ограничьте повторы, чтобы сбойная задача не удерживала пул в насыщенном состоянии.
Сохраняем границы приватности и совместимости
Подсказка намеренно приблизительна и может быть уменьшена. Страница должна работать, если свойства нет, значение мало или оно не совпадает с прежним наблюдением. Проверяйте поддержку Worker и предусмотрите для коротких задач запасной путь в главном потоке или последовательное выполнение. Не объединяйте hardwareConcurrency с измерениями времени, графики, шрифтов или хранилища для идентификации человека или устройства.
Объясняйте выбор ресурсов, если он влияет на батарею, трафик или загрузку. Локальный пул Worker не дает разрешения отправлять данные куда-либо еще. Если процесс меняется с локальной обработки на удаленный сервис, запросите явный выбор и сообщите, какие данные покидают устройство. В журналах оставляйте только измерения, необходимые для работы очереди, без исходного содержимого и лишних аппаратных подробностей.
Сначала классифицируем задачу
Сначала разделите задачи на CPU-зависимые, сетевые и использующие общее состояние. Для независимых вычислений число Worker можно постепенно увеличивать, пока пропускная способность не перестанет расти. Сетевая задача чаще ограничена ответом сервиса, поэтому дополнительные Worker лишь увеличат давление.
Отделяйте независимые элементы от упорядоченных этапов. Независимые результаты можно завершать в любом порядке и затем восстановить по номеру. Для зависимых этапов явно храните порядок, а не запускайте Worker на каждый шаг.
Одинаково определяйте измеряемую операцию: подготовка входа, передача сообщения, выполнение, обработка результата и очистка. Иначе быстрый Worker скроет задержку подготовки на странице.
До выбора размера пула опишите отмену и ошибку одной задачи. Задача без понятного завершения может занять Worker надолго и исказить сравнение режимов.
Проектируем жизненный цикл очереди
У ограниченной очереди должны быть правила приема, выполнения и завершения. При достижении предела можно отклонить работу, заменить устаревшее обновление или показать ожидание, но нельзя молча накапливать бесконечный ввод.
Один компонент должен владеть состоянием очереди, а Worker только своей текущей задачей. Сообщение содержит короткий идентификатор, ответ сообщает успех, ошибку или отмену, поэтому запоздалый ответ не перезапишет новую задачу.
Для активной задачи задайте тайм-аут и отмену. При завершении рассчитывайте ее один раз, освобождайте Worker и обновляйте измерения для следующего решения.
Учитываем передачу и память
Структурированное клонирование копирует объекты, а transferable-буфер может передать владение, если это поддерживает API. Сравнивайте оба варианта на реальных данных, а не только время вычисления.
Ограничивайте размер входа и освобождайте ссылки после завершения. Если крупные массивы держат страница, очередь и Worker, пиковое потребление памяти растет даже при малом числе активных задач.
Задайте срок хранения результатов. Выводите только данные текущего представления, большие списки разбивайте на страницы и не храните копии отдельно для журнала и интерфейса.
Учитываем видимость и питание
Когда документ скрыт, приостановите необязательную работу или снизьте ее приоритет. После возвращения проверьте очередь заново: поиск или предварительный просмотр могли измениться.
На мобильных устройствах постоянный пул расходует батарею и выделяет тепло. Режим экономии должен менять прикладной максимум, а не трактовать подсказку как емкость батареи.
Видимость и питание нужны для планирования, но не для идентификации. Не отправляйте эти наблюдения сервису без явного выбора пользователя.
Делаем резервный путь наблюдаемым
В точке использования проверьте Worker и нужный обмен сообщениями. При отсутствии поддержки перейдите к последовательному пути с тем же форматом результата и доступной отменой.
Показывайте состояния подготовки, обработки, паузы и ошибки, но не обещайте скорость на основании числа Worker.
Проверьте сбой Worker, неверный результат, тайм-аут, отмену во время передачи и навигацию. Каждый случай должен завершить задачу, освободить ресурсы и оставить очередь пригодной для остальных.
Ограничьте повторы и предлагайте их только когда они могут изменить исход. Постоянная ошибка должна быть понятна пользователю, а интерфейс не должен ждать бесконечно.
Превращаем измерения в обратимое решение
Сравнивайте холодный и теплый запуск на типичных входных данных, фиксируя подсказку, прикладной предел и версию браузера. Представляйте результат как изменяемую настройку и измеряйте снова после изменения нагрузки.
Источники
Для связанных решений о возможностях браузера см. руководство по согласованности WebAssembly и руководство по планированию емкости контекстов. Эти эксплуатационные измерения нужно отделять от грубой подсказки браузера о параллельности.
Похожие статьи
Переведите BotBrowser из исследований в продакшн
Используйте эти руководства, чтобы понять модель, а затем перейти к кроссплатформенной валидации, изолированным контекстам и масштабируемому браузерному развертыванию.