DirectSurface UIDirectSurface UI
开始使用
文档/性能与调试

Runtime Diagnostics Panel

import { RenderRuntimeDiagnosticsPanel, type RuntimeDiagnosticsState } from 'ds-ui'

Runtime Diagnostics Panel 是运行时诊断面板,用于查看 paint/layout request、热点聚合、调用栈、dirty target 和诊断快照。它是排查“为什么一直重绘”“为什么一直 layout”的主要工具。

在完整应用中,推荐通过 DevTools 开发工具 的 Runtime tab 打开该能力。单独使用 RenderRuntimeDiagnosticsPanel 更适合 demo、测试或自定义诊断容器。

运行时诊断指南 的区别:

  • 指南讲排查流程和操作顺序。
  • 本页讲面板字段、指标含义、过滤方式和典型案例。

核心数据结构

RenderRuntimeDiagnosticsPanel 接收 RuntimeDiagnosticsState

const state: RuntimeDiagnosticsState = {  paintRequestDebugEnabled: true,  paintRequests: [],} const panel = new RenderRuntimeDiagnosticsPanel({ state })

实际应用中,paintRequests 应由运行时 host 收集。面板只负责展示、过滤、聚合和查看详情。

构造参数

参数 类型 说明
state RuntimeDiagnosticsState 当前诊断状态。
onRefresh () => RuntimeDiagnosticsState 刷新状态。
onTogglePaintRequestDebug () => RuntimeDiagnosticsState 开关 paint request debug。
onClearPaintRequestHistory () => RuntimeDiagnosticsState 清空请求历史。
onExportDiagnosticsSnapshot () => RuntimeDiagnosticsSnapshot 导出诊断快照。

面板区域

区域 说明
Toolbar 刷新、开关 stack/debug、清空历史、导出快照。
Filter Bar 切换 Requests/Hotspots、kind、source 和搜索。
Summary 当前请求数量、过滤数量、热点数量、stack 状态。
List 请求列表或热点列表。
Detail Inspector 选中 request/hotspot 的完整对象详情。

Requests 视图

Requests 视图保留时间顺序,适合观察“刚才那一次操作触发了什么”。

重点字段:

字段 含义 判断方式
seq 请求序号 连续增长说明仍在产生请求。
kind framelayout layout 高频通常比纯 paint 更危险。
source 请求来源 pipeline、overlay、runtime、window、debug 等。
target 发起请求的 RenderObject 首先定位到具体组件。
reason 请求原因 判断是否是合法交互、动画、光标或异常同步。
alreadyScheduled 当时是否已有帧调度 大量 true 说明请求过密。
layoutNeeded 当时是否已有 layout 需求 持续 true 可能存在 layout 循环。
dirtyLayers 脏图层 判断局部 dirty 是否被放大。
stack 调用栈 定位触发 markNeedsLayout/markNeedsPaint 的代码。

Hotspots 视图

Hotspots 按 target、kind、source、reason 聚合,适合观察长时间采样中的最高频来源。

重点字段:

字段 含义
count 同类请求次数。
firstSeq / lastSeq 首次和最近请求序号。
firstTime / lastTime 首次和最近请求时间。
alreadyScheduledCount 请求时已经有帧调度的次数。
layoutNeededCount 请求时已经有 layout 需求的次数。
dirtyLayerCount 涉及 dirty layer 数量。
layoutTargets 本次聚合涉及的 layout 目标。
paintTargets 本次聚合涉及的 paint 目标。

排查时优先看 count 最高且业务上不应持续变化的 hotspot。

过滤器

过滤器 用途
View Mode 在 Requests 和 Hotspots 间切换。
Kind Filter 只看 framelayout
Source Filter 只看 pipeline、overlay、runtime、window、debug 等来源。
Query Filter 按 target、reason、source、stack 文本搜索。

常用组合:

  • 空闲持续重排:kind = layout,按 count 看 hotspots。
  • hover 卡顿:query 输入组件名或 hover
  • 弹窗问题:source = overlay
  • 窗口问题:source = window

debugState

面板自身提供 debugState(),适合测试和诊断:

字段 说明
requestCount 原始请求数量。
filteredRequestCount 当前过滤后的请求数量。
aggregateCount 当前热点数量。
selectedSeq 当前选中的 request seq。
selectedAggregateKey 当前选中的 hotspot key。
paintRequestDebugEnabled 是否开启请求调试。
viewMode 当前视图模式。
kindFilter 当前 kind 过滤。
sourceFilter 当前 source 过滤。
queryFilter 当前搜索文本。
listLabels 当前列表显示文本。
detailRoots 详情 ObjectInspector 根路径。
summaryText 面板摘要文本。

典型案例

空闲时持续 layout

现象:

kind: layout
target: RenderReviewSidebar
stack: RenderReviewSidebar.setItems -> RenderMedicalRecordEditor.performLayout

判断:

performLayout() 中同步调用子组件 setter,且 setter 即使数据不变也会 markNeedsLayout()

修复:

  • 对传入 items 做签名比较。
  • 数据没变时不调用 setter。
  • 避免 layout 阶段创建新数组再写入子组件。

空闲时持续 paint

现象:

kind: frame
target: RenderTabs
stack: underline animation reset -> RenderTabs._syncUnderline

判断:

动画控制器可能在没有 tab 切换时反复 reset,导致持续 paint。

修复:

  • 只在 active tab 或目标 underline 变化时启动动画。
  • 相同值不 reset 动画。
  • 动画结束后停止通知。

输入光标导致大文档重绘

现象:

kind: frame
target: RenderMedicalRecordEditor
reason: caret

判断:

光标闪烁不应让整个大文档持续重绘。需要检查 dirty 范围是否被放大。

修复:

  • 光标绘制走局部 dirty rect。
  • 光标闪烁不触发布局。
  • 可视页绘制不要因为光标而扫描全量页。

overlay 请求过多

现象:

source: overlay
target: PopupHost

判断:

popup、tooltip、dropdown 或 modal 可能在滚动/hover 中反复刷新位置或重建内容。

修复:

  • 只有 anchor rect 变化时刷新 popup 位置。
  • hover tooltip 加延迟和相等判断。
  • 弹窗内容数据没变时不重建树。

快照导出

导出快照适合现场问题复现:

  1. 开启 paint request debug。
  2. 执行最小复现动作。
  3. 导出 Runtime Diagnostics Snapshot。
  4. 提交给开发分析。

快照应脱敏:

  • 不包含患者隐私。
  • 不包含账号 token。
  • 不包含完整病历正文。
  • 不包含超大业务数组。

性能注意事项

  • 开启 stack 采集会增加额外开销,只在排查时打开。
  • 请求历史应有上限,不要无限保存。
  • 面板本身也会布局和绘制,复杂问题复现后应关闭它再验证真实性能。
  • 详情 ObjectInspector 展开大对象时应分批,避免诊断工具造成新的卡顿。

和其他工具的分工

工具 负责
Runtime Diagnostics Panel 谁请求 layout/paint,为什么请求。
性能浮层 当前帧是否慢,趋势是否异常。
Layout Inspector 节点在哪里,rect 和命中是否正确。
ObjectInspector 对象内部状态是什么。
浏览器 Performance 浏览器主线程具体耗时在哪里。
Heap Snapshot 关闭后谁还持有对象。

相关文档