> **本文回答**：怎么用 Chrome DevTools 抓 vjmap 性能问题 —— Performance 录制、Memory、FPS、WebGL inspector。

## 一、最重要的 2 个面板

| 面板 | 用途 |
|---|---|
| Performance | 录 30 秒找出哪个函数吃掉了主线程 |
| Memory | 找内存泄漏、对象计数 |

次要：Lighthouse（整体性能）、Rendering（FPS meter、paint flashing）。

## 二、Performance 录制流程

1. F12 → Performance → 齿轮勾 `Screenshots` + `Memory`
2. 按 **录制** 按钮
3. 做典型操作（缩放、平移、搜索、加载数据）15~30 秒
4. 停止
5. 看 Main thread 的火焰图 / Summary 饼图

重点看：

- **长任务**（红色棒条 > 50ms）：那一刻主线程被卡住
- 火焰图里最深的栈 → 通常是罪魁函数

## 三、常见罪魁定位

| 火焰图看到 | 可能原因 | 对应文档 |
|---|---|---|
| `rebuild bucket` / `upload buffer` 长 | 未 bulk / 未 dynamic | [batch-rendering](../../../vjmapext/references/perf/batch-rendering.md) |
| `encodeGeometry` 多次 | 每条 changed() 都重算 | [style-only-fast-path](../../../vjmapext/references/perf/style-only-fast-path.md) |
| `style layout` 占大头 | DOM Marker 太多 | [large-markers](large-markers.md) |
| `paint` 每帧占 10ms+ | 画面元素过多 / 表达式过深 | [map-style/expressions](../map-style/expressions.md) |
| `queryRenderedFeatures` 频繁 | mousemove 没节流 | [event-throttling](event-throttling.md) |
| GC 红色 | 大对象频繁创建 | 池化 / 复用 |

## 四、FPS meter

Chrome → DevTools → `Cmd+Shift+P` 或 `Ctrl+Shift+P` → 输入 "rendering" → Show Rendering → 勾 `Frame Rendering Stats`：

- 右上角显示实时 FPS、GPU memory、DOM nodes 数
- 开发时一直开着

## 五、Paint flashing

同一个 Rendering 面板，勾 `Paint flashing`：

- 每次重绘的区域会闪绿色
- 帮助定位"哪些 UI 元素被 over-invalidate"

## 六、vjmap 内置 metrics

```js
// FX（vjmapext 唯一内置 metrics API）
mapcadLayer.fx.getMetrics();
// 每 bucket 的 active / points / lines / shadertoys 分布

// 实体渲染管线没有公开 metrics API（renderPipeline.getBucketStats 不存在）；
// 用 Performance 录制 / Memory 快照代替
```

## 七、Memory Snapshot 步骤

1. Memory → `Take heap snapshot`（Snapshot 1）
2. 做操作（打开关闭地图 10 次）
3. 点垃圾桶强制 GC
4. 再打 Snapshot 2
5. `Comparison` 模式对比
6. 搜 `Marker` / `Map` / `MapCadLayer` 看增量

示例：发现 20 个 Marker retained → 查 retainers 路径 → 找到某 Vue 组件没 remove。

## 八、Allocation instrumentation on timeline

Memory → `Allocation instrumentation on timeline` → 录制时每次分配都打点：

- 适合找"谁在一直 new 对象"
- 比如 mousemove 里每次 new Point2D → 优化用 pool

## 九、WebGL inspector（第三方扩展）

Chrome 扩展 `Spector.js`：

- 录一帧的所有 drawCall
- 看每个 drawCall 的 texture / uniform / buffer
- 用于自定义 WebGL 层调试

## 十、CPU 限速

DevTools → Performance → 齿轮 → `CPU: 4× slowdown`：

- 模拟低端机
- 录制后看在慢机器上的表现

## 十一、性能预算

| 指标 | 目标 |
|---|---|
| FPS | ≥ 55 平稳；低端 ≥ 30 |
| 主线程长任务 | < 50ms |
| 帧均 | < 16.7ms（60 FPS）/ < 33ms（30 FPS）|
| 内存增长 | 长时间运行后不持续上涨 |

## 十二、诊断清单（按顺序排查）

1. 打开 Rendering → Frame Rendering Stats → 观察 FPS 是否稳定 60
2. 如果 < 60：Performance 录 15s
3. 看 Main 栈最宽的函数：
   - vjmap 底座？看 [map-style/layer-styles](../map-style/layer-styles.md) + [expressions](../map-style/expressions.md)
   - mapcadLayer 渲染？看 [render-buckets](../../../vjmapext/references/perf/render-buckets.md) + [batch-rendering](../../../vjmapext/references/perf/batch-rendering.md)
   - 业务代码？看 [event-throttling](event-throttling.md)
4. 内存一直涨 → Memory 对比快照 → [memory-leaks](memory-leaks.md)

## 十三、生产环境采样

```js
if (navigator.sendBeacon && window.PerformanceObserver) {
  new PerformanceObserver(list => {
    for (const e of list.getEntries()) {
      if (e.duration > 100) {
        // 长任务 → 上报
        navigator.sendBeacon('/perf', JSON.stringify({
          name: e.name, duration: e.duration, ts: Date.now()
        }));
      }
    }
  }).observe({ type: 'longtask', buffered: true });
}
```

监控用户真实设备上的长任务。

## 十四、常见坑

1. **本机跑 60 FPS 就以为没事**：生产低端机一大半 30-；必用 CPU slowdown 测。
2. **DevTools 关上后 FPS 变好**：DevTools 自身开销大；务必 close 后评估。
3. **Paint flashing 整片绿**：某个高频重绘元素（Marker layer）；迁 Symbol。
4. **Memory 数字看 `usedJSHeapSize`**：只反映 JS 堆，不含 GPU 内存；GPU 侧用 DevTools 的 Memory/GPU 面板或观察 `webglcontextlost` 事件。
5. **录制时间太短（<5s）**：看不到模式；至少 15s。

## 相关

- 总览 → [overview](overview.md)
- 事件节流 → [event-throttling](event-throttling.md)
- 内存泄漏 → [memory-leaks](memory-leaks.md)
