Compute Pressure API: адаптивные интерфейсы без перегрева
Когда приложение выжимает процессор «на полную», пользователь чувствует задержки ввода, рывки анимаций и даже слышит, как ревут вентиляторы. Compute Pressure API позволяет напрямую узнать, насколько устройство перегружено, и динамически снизить аппетиты кода до комфортного уровня.
Базовая проверка поддержки
if ('PressureObserver' in globalThis) {
// Браузер уже умеет работать с Compute Pressure API
}
Эта проверка универсальна — сработает и в главном потоке, и в worker’ах. Дальше нужно учитывать, что сам API может быть «пустой оболочкой», если ОС или железо не передают метрики.
Узнайте поддержку на caniuse.
Быстрый старт: слушаем CPU
const observer = new PressureObserver((records) => {
for (const {state, time} of records) {
console.log(`CPU-вычисления: ${state} @ ${time.toFixed(0)} мс`);
}
});
// «0» означает, что колбэк придёт только при смене состояния,
// а не с постоянным интервалом.
observer.observe('cpu', {sampleInterval: 0});
state
может быть:
Состояние | Что значит |
---|---|
nominal | Всё хорошо, запас мощности. |
fair | Нагрузка умеренная, автономность может падать. |
serious | Процессор сильно греется, возможен троттлинг. |
critical | Устройство близко к пределу — пора снижать нагрузку. |
Реактивное снижение качества
Представьте видеоконференцию с отображением большого количества участников. Чтобы не забить процессор, уменьшаем число одновременно отображаемых потоков, если вычисления процессора выросло до critical
.
let visibleStreams = 9; // стартовое качество
const MIN_STREAMS = 1;
const STEP_MS = 30_000;
const observer = new PressureObserver(handlePressure);
observer.observe('cpu', {sampleInterval: STEP_MS});
function handlePressure(records, obs) {
const {state} = records.at(-1); // берем последнее измерение
if (state === 'critical' && visibleStreams > MIN_STREAMS) {
visibleStreams--;
applyLayout(visibleStreams); // собственная функция раскладки
}
// плановое выздоровление: если состояние долго не меняется,
// вручную триггерим обработку для повторной проверки.
setTimeout(() => obs.takeRecords().length || handlePressure(records, obs), STEP_MS);
}
Тонкая настройка частоты выборки
Нужно получать показания каждые 2 секунды? Передайте интервал в миллисекундах:
observer.observe('cpu', {sampleInterval: 2_000});
Браузер может выбрать чуть другую частоту — спецификация специально разрешает «размывать» данные для защиты от side-channel атак.
Отключаем наблюдение
observer.unobserve('cpu'); // перестаём слушать только CPU
// …
observer.disconnect(); // полностью убираем все подписки
Используйте takeRecords()
прямо перед disconnect()
, чтобы не потерять оставшиеся события:
const pending = observer.takeRecords();
// … сохраняем статистику …
observer.disconnect();
Безопасность и конфиденциальность
Браузеры вводят несколько защит:
- Rate Obfuscation — если скрипт дёргает состояние слишком часто, колбэк временно «глушится».
- Same-Origin Restriction — доступен только активной вкладке (или разрешённым
iframe
) того жеorigin
. - Break Calibration — границы состояний слегка плавают, чтобы злоумышленник не смог «калибровать» канал связи между вкладками.
Рассчитывайте на это и не пытайтесь добиться миллисекундной точности — API предназначен для грубой адаптации интерфейса, а не для профилирования.
Паттерны использования
Сценарий | Что делать |
---|---|
Тяжёлые эффекты Canvas/WebGL | Понижать разрешение холста на serious/critical. |
AI-обработка в браузере | Уменьшать batch-size модели, отключать нетривиальные аугментации. |
Прогрессивные анимации | Замедлять кадровую частоту или переходить на CSS-анимации. |
Игровой движок | Снижать дальность прорисовки, количество частиц. |
Советы по дизайну UX
- Не всплывающие алерты, а тихие визуальные индикаторы (иконка, цветовой маркер) — пользователю важен не факт перегрузки, а то, что приложение заботится о плавности.
- Дайте выбор: кнопка «Всегда максимум качества» для энтузиастов и режим «Авто» для остальных.
- Помните про доступность: индикатор нагрузки должен дублироваться текстом («Нагрузка высокая»), а не только цветом.