Compute Pressure API:隐私安全的自适应负载
把 Compute Pressure 作为可选的粗粒度信号,安全地调整可回退负载,而不把压力变成设备身份。
BotBrowser Team
Compute Pressure API 暴露影响浏览器负载的粗粒度压力视图。它可以帮助应用选择更轻的渲染路径、延后可选工作,或在状态变化后恢复质量。它不是 CPU 计量器、设备指纹或宿主诊断。BotBrowser 受控上下文可以运行获授权的 fixture,在 runtime 暴露 API 时检测 PressureObserver 并记录可见结果;BotBrowser 不能制造压力源、强行启用支持,也不能保证所有宿主产生相同的变化。相邻信号可参考 Device Memory 与 Web 性能、硬件并发与 worker 规划以及 PerformanceObserver 与应用健康度。
TL;DR
- 把
PressureObserver当作可选的粗粒度信号,用于可逆的负载决策。 - 由拥有工作流的组件负责观察者、callback 清理和适配状态。
- 不要把
nominal、fair、serious或critical变成设备、个人或账号标签。 - API 缺失、被拒绝或在 worker 中不可用时,仍保留可用的基础路径。
- 记录
reduced、restored或unavailable等有界结果,不保留长期压力历史。
目录
把压力读作粗粒度能力信号
Compute Pressure 规范定义浏览器观察模型,而不是对物理处理器的承诺。应用创建 PressureObserver,提供 callback,并观察 cpu 之类的 source。callback 接收带有状态和时间的 PressureRecord。状态词汇有意保持粗粒度:nominal、fair、serious 和 critical 表示压力区间,不是可以跨系统比较的百分比。
MDN Compute Pressure API 参考说明 API 表面与可用性。先检测构造函数和实际使用的方法。缺少 PressureObserver 只说明该 runtime 没有通过这条路径提供可选信号,并不证明宿主空闲、过载、快速或不安全。权限策略、浏览器版本、worker 类型或平台隐私选择都可能造成缺失。
Chrome Compute Pressure 指南把适配描述为保持响应能力的方法。把它当作用户可见决策的模型,不要当作每个 webview 的兼容性承诺。source 和浏览器版本决定哪些状态会暴露。基础体验应在扩展观察之前就能正常工作。
不要把压力与 navigator.hardwareConcurrency、navigator.deviceMemory 或性能条目混为一谈。浏览器可能合并或延后变化,同一宿主上的两个页面也可能看到不同状态。状态还不能说明是哪一个标签页、进程、扩展或温度条件造成了它。不要把这些问题写入应用记录。
const pressureState = {
source: 'cpu',
state: 'unavailable',
policy: 'baseline',
sequence: 0,
};
选择可逆的负载策略
适配应该只改变可选工作,同时保留用户的主要任务。serious 状态可以暂停预览、减少粒子或延后索引,但不应删除编辑、移除可访问控件或降低必要校验。策略负责决策,观察者只提供提示。
| 观察结果 | 负载动作 | 可见契约 | 恢复条件 |
|---|---|---|---|
unavailable | 保留基础预算并跳过可选观察 | 核心任务仍可使用 | 运行时明确变化后再评估 |
nominal | 允许正常的可选预算 | 质量和控件保持可用 | 继续使用基础限制 |
fair | 延后非必要工作并限制并发 | 告知预览被延后 | 以后续观察状态恢复 |
serious | 暂停后台工作并选择轻量路径 | 保留输入、焦点和取消 | 仅从新记录恢复 |
critical | 停止可选工作并保留已提交结果 | 解释可选工作暂停 | 需要新状态和安全预算 |
这些是策略结果,不是 CPU 利用率。照搬另一个 runtime 的限制可能造成振荡。恢复前要求更新记录,同时允许用户明确重试预览。
为前台、后台和保留数据分别设置预算。限制待处理任务,取消过期工作,并记录 worker 是提交、被替换还是取消。恢复时保留上一个可见结果;空白占位会让压力状态看起来像数据丢失。
可访问性也属于变化契约。只公告有意义的模式变化,不重复每个 callback;保持键盘焦点、文字替代和重试动作。轻量模式可以改变计算,不能削弱用户理解和控制任务的能力。
控制观察所有权与隐私边界
创建 PressureObserver 的组件拥有观察者、callback、策略和清理动作。路由变化、worker 关闭或功能禁用时调用断开。callback 只复制状态和本地序号,不应在其中执行网络请求或大规模序列化。
浏览器可能以保护隐私的节奏交付记录。不要从间隔推导高分辨率时间线。时间只能排序本组件记录,不能证明用户动作、核心数量或温度事件。遥测中应四舍五入或省略时间,并只保留必要期限。
不要把压力状态与账号、URL、locale 或设备连接。即使单个字段看似无害,组合后也可能成为持久行为信号。有限会话可以只保留 policy=paused 聚合结果;做整体统计时先去掉账号标识并说明采样方式与保留期限。
worker 可以观察自己的 source,但页面决定结果是否仍属于当前路由。发送带本地序号的 workload-reduced,不要发送完整历史。跨文档时校验 origin 和 schema。API 缺失应产生 unavailable,不能成为配置档案中的低能力标签。
当 runtime 暴露 PressureObserver 时,BotBrowser 可以在受控上下文运行获授权页面并比较可见适配结果。它不能创造压力、控制另一标签页、认定宿主层原因,也不能证明生产环境有相同节奏。
用有界 fixture 验证变化
使用包含一个可选负载和一个已提交结果的合成页面。fixture 检查能力、安装观察者、应用有界变化并断开;不收集账号数据,也不保存历史。没有 API 的运行仍应产生 unavailable 行。
const record = { source: 'cpu', state: 'unavailable', policy: 'baseline', sequence: 0 };
let observer;
if ('PressureObserver' in globalThis) {
observer = new PressureObserver(records => {
const latest = records.at(-1);
record.sequence += 1;
record.state = latest?.state ?? 'unavailable';
record.policy = record.state === 'serious' || record.state === 'critical' ? 'reduced' : 'normal';
});
await observer.observe('cpu');
}
try {
await runBoundedFixture({ limit: 8, signal });
} finally {
observer?.disconnect();
}
fixture 只记录 runtime 暴露的状态,不强行制造状态。合成的 unavailable 仍能验证基础路径和清理动作。
| Fixture 情况 | 预期记录 | 能证明什么 | 不能证明什么 |
|---|---|---|---|
| 缺少构造函数 | unavailable、baseline | 能力检测和安全回退 | 宿主处于空闲 |
| 观察者连接 | 可见状态与 normal 或 reduced 策略 | 有界记录的所有权 | 物理 CPU 百分比 |
| 新的严重或临界状态 | 新 sequence 的 reduced | 暂停且不丢失结果 | 所有标签页共享状态 |
| 路由或 worker 清理 | disconnect() 后没有新提交 | 防止旧 callback | 不存在已排队 callback |
| 用户恢复可选工作 | 使用当前输入的新任务 | 可逆恢复 | 宿主全局压力消失 |
只记录合成且有界的 browserVersion、runtimePath、source、state、policy、sequence、fixtureId 和 outcome。把 unsupported-source 与 unavailable 分开。浏览器、worker、负载或隐私策略变化后重放,并比较第一个不同字段。
Public sources
- Compute Pressure specification
- MDN: Compute Pressure API
- Chrome for Developers: Compute Pressure API
- BotBrowser: Advanced features
实践结论
检测 PressureObserver,保留可用的基础路径,让有界策略决定暂停或恢复可选工作。为观察者和清理动作指定一个所有者,短暂保存粗粒度记录,并保留已提交结果。变化后重放 fixture,从第一个可见变化状态作出决定。
本文属于指南: Web 平台能力面:一致性复核地图