Skip to content

性能基准 ​

一键跑分:在 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),看每个功能带来的增量代价——这个相对关系才稳定、可解释。表格同列对最优(绿)/最差(红)高亮,一眼看出哪个配置最贵。

基于 MIT 协议发布(内部使用)