На главную

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

  1. Не всплывающие алерты, а тихие визуальные индикаторы (иконка, цветовой маркер) — пользователю важен не факт перегрузки, а то, что приложение заботится о плавности.
  2. Дайте выбор: кнопка «Всегда максимум качества» для энтузиастов и режим «Авто» для остальных.
  3. Помните про доступность: индикатор нагрузки должен дублироваться текстом («Нагрузка высокая»), а не только цветом.