给 LLM 喂什么:profile 数据的三种裁剪方式

封面信息图

在构建前端性能智能诊断 Agent 时,所有架构师面临的第一道核心工程难关就是:如何处理 Chrome 导出的庞大 Performance Profile 数据?

一份录制了 5 秒用户交互的真实 Chrome Trace JSON 文件,体积通常在 30MB 到 150MB 之间,内部包含了几十万个底层事件(Event Slices)、V8 内部元数据、线程通信管道日志以及海量的 GPU 光栅化坐标。

直接把整份文件喂给大模型显然是天方夜谭(瞬间爆掉 Context Window)。而如果粗暴地只截取头部的 1000 行,模型拿到的全是无意义的环境初始化元数据。

要让大模型在有限的上下文预算(例如 4k ~ 16k Tokens)内精准命中瓶颈,必须对 Profile 数据进行多维度的数学降维与特征裁剪

本文深度拆解我们在生产实践中验证过的 三种 Profile 数据裁剪范式与适用场景


三种裁剪方式的架构对比

┌─────────────────────────────────────────────────────────────┐
│ 方式 1: 瓶颈聚合裁剪 (Bottleneck Top-down Aggregation)      │
│    - 提取: Top-N Self Time / Total Time 聚合热点表           │
│    - 体积: ~ 1.5 KB                                         │
│    - 场景: 快速初筛、CI 自动化门禁、高频快速体检            │
├─────────────────────────────────────────────────────────────┤
│ 方式 2: 时序长任务切片裁剪 (Long Task Timeline Slicing)      │
│    - 提取: 耗时 > 50ms 的长任务上下文及微观嵌套调用栈         │
│    - 体积: ~ 8.0 KB                                         │
│    - 场景: 用户交互掉帧(INP / 冻结)靶向排查                │
├─────────────────────────────────────────────────────────────┤
│ 方式 3: 渲染管线多维特征融合 (Pipeline Multi-track Distill)   │
│    - 提取: 主线程 JS + 强制回流计数 + 网络瀑布 + 帧率关联图  │
│    - 体积: ~ 12.0 KB                                        │
│    - 场景: 复杂大促活动页、万级表格全链路深度会诊            │
└─────────────────────────────────────────────────────────────┘

裁剪方式 1:瓶颈聚合热点表(Top-down Aggregation)

核心原理

跳过所有的时序发生细节,仅通过采样点(Samples)统计每个函数在全生命周期内的 自身耗时(Self Time)总耗时(Total Time),按耗时倒序输出一个紧凑的 Markdown 表格。

// 数据形态示例 (输入给 LLM 的 Prompt 片段)
[Top 5 CPU 耗时函数清单]
1. `filterTreeNodes` (src/utils/tree.ts:84) - Self: 340ms (48.2%), Total: 410ms
2. `deepClone` (src/utils/clone.ts:12) - Self: 180ms (25.5%), Total: 180ms
3. `calculateLayout` (src/views/Canvas.vue:120) - Self: 60ms (8.5%), Total: 520ms

优劣分析

  • 优势:体积极限小(< 2KB),Token 消耗微乎其微,对纯 CPU 密集型死循环、复杂递归算法的定位准确率高达 95%
  • 劣势:丢失了时间序列信息,无法看出函数是在页面初次挂载时执行的,还是在用户点击按钮时执行的。

裁剪方式 2:时序长任务切片(Long Task Slicing)

核心原理

过滤掉所有小于 50ms 的微小事件,仅将主线程上发生的长任务(Long Task)提取为一个独立的微型调用树(Sub-calltree),并保留其发生的时间戳与父子调用链。

// scripts/slice-long-tasks.ts
export function extractLongTaskSlices(traceEvents: any[]) {
  const longTasks = traceEvents.filter(
    (e) => e.name === 'RunTask' && (e.dur || 0) >= 50000 // >= 50ms
  );

  return longTasks.map((task) => ({
    startTime: `${(task.ts / 1000).toFixed(1)} ms`,
    duration: `${(task.dur / 1000).toFixed(1)} ms`,
    // 递归提取该长任务内部耗时最长的主干调用栈
    callStack: extractCriticalPath(task),
  }));
}
// 数据形态示例
[
  {
    "taskDuration": "184.2 ms",
    "triggerPhase": "User Click on Button#submit",
    "callChain": "handleClick (Order.vue:45) -> submitOrder -> validateForm -> validateComplexRegexp (validator.ts:112)"
  }
]

优劣分析

  • 优势:能够清晰还原“某个特定的用户手势触发了哪一条长任务调用链”,非常适合治理新一代 Web Vitals 交互指标 INP(Interaction to Next Paint)
  • 劣势:如果页面上存在数十个连续的 40ms 任务(虽然不是 Long Task 但累积造成卡顿),可能会被该规则漏网。

裁剪方式 3:渲染管线多维特征融合(Multi-track Distill)

核心原理

将主线程计算、渲染引擎行为(Layout / Paint / Composite)与网络资源下载三个原本分离的泳道进行关联聚合,输出一份结构化指标画像:

{
  "summary": { "totalDuration": "4.8s", "droppedFrameCount": 18 },
  "forcedLayoutMetrics": {
    "totalCount": 42,
    "worstCulpritLocation": "src/components/Table/VirtualRow.vue:89",
    "associatedJsFunction": "updateRowOffset"
  },
  "networkBottlenecks": [
    { "url": "/assets/echarts.bundle.js", "size": "840KB", "blockingDuration": "1.2s" }
  ],
  "topCpuHotspots": [
    { "func": "computeMatrix", "file": "src/math/matrix.ts:32", "selfTime": "420ms" }
  ]
}

优劣分析

  • 优势:信息密度极高,给大模型提供了完整的“全景证据链”。模型可以推理出“因为网络加载了超大 JS,导致主线程解析阻塞,随后在组件挂载时触发了 42 次强制同步回流”这种深层跨阶段因果链路。
  • 劣势:需要编写稍微复杂的 Trace 解析器,输入 Token 占用约 10k ~ 15k。

选型与落地方案推荐

在生产自动化流水线中,我们推荐采用**“渐进式两阶段裁剪策略”**:

[流水线触发性能分析]
          │
          ▼ (第一阶段: 使用【方式 1 瓶颈聚合】进行 2 秒快速体检)
  ├── 若仅发现简单的单一函数算力过高 ──> 直接输出修复 Diff,流程结束
  │
  └── 若存在复杂的交互卡顿与回流 ──> 升级触发【方式 3 多维特征融合】进行深度会诊

通过这套裁剪分流策略,团队在保障 90% 以上诊断准确率 的同时,将单次调用的 Token 账单削减了 75%

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐