性能基准
一键跑分:在 SDK 公共 API 层(trace.track())对独立实例做三维度基准——同步吞吐 / 端到端处理延迟 / 冷启动,跨 4 个装配场景(基线(Tracking) → 全插件 → 全插件+采样 → 全插件+beforeEmit)做相对对比,量化各功能的性能代价。采样与统计交给业内常用的 tinybench。
测量口径
全程 mock 静默(不出网、不挂观测钩子),跑分实例由 runner 自建自销、不影响其他页。数字是本机单次运行的相对值,每格带 rme(相对误差幅度)标可信度,用于配置间横向对比,不跨机器可比。
指标怎么算、为什么这么设
通用口径(三维度共用)
- 在公共 API 层测(
trace.track()):业务只接触公共 API,这里的数字才是业务真正承受的成本;底层buildPipeline的 micro-bench 不反映真实调用开销。 - mock 静默 +
silentFetch:上报请求直接回200、不出网,排除网络波动,只留 SDK 自身的 CPU 成本;且不挂onReported、不写观测缓冲(吞吐场景),避免 playground 的记录开销(pushRecord的new Date、响应式数组重建)淹没被测对象。 - 显式
debug: false硬关 Debug Bridge:页面级运行期 flag__tripo_lens_debug(DevTools「管线」联调残留)会让每条事件广播约 7 条postMessage结构化克隆;跑分的紧循环下这会洪泛消息队列直至标签页 OOM 崩溃,且严重失真。硬关后跑分实例不受该 flag 影响。 - 独立实例、跑完即
destroy():每个场景/维度自建实例,互不干扰,也顺带验证destroy的清理是否干净。 - 用
tinybench当采样 + 统计引擎:业内常用做法。它自动warmup(让 JIT 优化到稳态)、按时间预算(time=300ms)自动采样、算 mean /rme/ 方差,避免手写采样循环的偏差。 - 报
rme(相对误差幅度)而非单点值:业内共识——单次跑分的数字必带不确定度。每格中心值后的±x%即rme,越小越可信;过大说明噪声重(GC、后台任务),该格别细究。 - 任务体内批量、再按批长均摊:单条
track()(~µs)低于浏览器performance.now()量化底(Chrome 非跨源隔离约0.1ms),tinybench 逐次迭代计时同样会被打成0。故吞吐/延迟维度在任务函数体内批量连发 B 条,使单次测量的批总耗时 ≫ 量化底,per-call = tinybench 结果 ÷ B(rme不随常数 B 变化,直接沿用)。 - 不设「裸装」场景:
trace.track()委托给TrackingPlugin提供的tracking-commands能力,未装TrackingPlugin时track()为 no-op(空转),无法基准;故最小可测基线为「仅 Tracking」。
同步吞吐 ops/s
怎么算:每个场景一个 tinybench task,任务体内连发 syncBatch=1000 条 track()(同步路径);tinybench 按时间预算自动采样这批墙钟耗时,换算 ops/s(= 1000 ÷ 批均摊每条 ms)并给出 rme。
为什么:track() 同步触发,这个数表示单位时间能塞进多少次调用、对主线程的同步占用有多轻——越高越好。
端到端处理延迟 ms/条
怎么算:每个场景一个 tinybench task,任务体内突发连发 latencyBatch=500 条 track(),借官方 onReported 钩子(track 是 P1 事件「入队即触发」)等这批全部入队,task 时长即「这批全链路墙钟跨度」,per-call = 批耗时 ÷ 批长。覆盖 调用 → pipeline(enricher→killSwitch→sampler→schema→PII→beforeEmit→serializer) → 入队 全链路,只认 type==='track' 的回调。
为什么:track() 同步返回后,真正的处理在异步链路里完成(beforeEmit 脱敏、采样判定、PII、序列化都在这里)。这条延迟反映事件从产生到进入传输队列的完整处理耗时,关系数据时效性与高频下的异步积压风险。只认 track 是为了过滤 webVitals / landing / pageview 等旁路上报;采样场景被丢弃的事件不触发 onReported,按发出条数均摊后正确体现「采样更省」——越低越好。
冷启动 ms
怎么算:每个场景一个 tinybench task,任务体即一次 new TripoLens() + await init() + destroy();单次 init 已在 ms 量级、远高于量化底,无需批量。tinybench 给出 mean + rme。
为什么:init() 含 device-id 解析、远程配置拉取、插件 setup——这是页面加载时的一次性开销,影响首屏,越低越好。
为什么不测内存
曾用「批量事件前后读 performance.memory.usedJSHeapSize 堆增量」测内存,但现代 Chrome 为缓解侧信道把 performance.memory 分桶量化并缓存(同值在约 20–30s 内重复返回)——几毫秒内连续读 before/after 拿到的是同一缓存值,差值恒为 0,测不出有效数据。故移除该维度,避免给出恒 0 的误导值。
为什么是「配置间相对对比」而非绝对阈值
绝对数值受机器、浏览器、当时负载影响极大,换台机器就不可比、定死阈值会频繁误报。改成同一次运行内跑多个装配场景做横向对比(基线(Tracking) vs 全插件 vs 采样 vs beforeEmit),看每个功能带来的增量代价——这个相对关系才稳定、可解释。表格同列对最优(绿)/最差(红)高亮,一眼看出哪个配置最贵。