第 12 章:性能优化与可观测性
本章定位
性能优化需要证据,不能靠感觉。本章把前端性能、监控、Trace 和 AI 系统的 token 成本、工具成功率统一到可观测性模型。
必须掌握清单
必须掌握
能解释 LCP、INP、CLS 分别代表什么。
相关答案: LCP 衡量视口内最大主要内容完成渲染的时间,INP 衡量用户交互到下一次绘制的整体响应延迟,CLS 衡量页面生命周期内意外布局偏移的程度。它们分别关注加载、响应和视觉稳定性,但不能覆盖所有性能问题。
具体例子: 首屏大图加载慢会拉高 LCP,点击搜索后主线程执行长计算会恶化 INP,未预留图片尺寸导致正文突然下移会增加 CLS。
能区分首屏性能、交互性能和内存问题。
相关答案: 首屏问题主要观察网络瀑布、资源优先级和关键渲染路径;交互问题关注主线程长任务、事件处理和渲染提交;内存问题关注对象是否持续被引用及回收后的堆趋势。三者需要不同证据,不能只看一个 Lighthouse 分数。
具体例子: 页面打开慢可能是大包阻塞;输入卡顿可能是每次键入都筛选十万行;切换路由多次后内存持续增长,则检查未清理的监听器和缓存。
能定位长任务和高频渲染。
相关答案: 用 Performance 记录找到超过 50ms 的主线程任务并展开调用栈,再用框架 Profiler 确认哪些组件为何提交。优化前先区分 JavaScript 计算、样式布局、绘制和无效状态更新。
具体例子: token 流期间火焰图显示根组件每 5ms 提交一次,Profiler 指向顶层
setState;把文本放到消息级 store 并按帧发布后,再对比提交次数和 INP。能把前端 trace 和服务端 trace 串起来。
相关答案: 浏览器在请求中传播符合系统约定的 trace context,服务端、数据库和工具调用创建子 span,并在日志中保留 trace ID。采集时要避免把 token、隐私数据或密钥直接放入 span 属性。
具体例子: 用户点击“发送”创建前端 span,请求携带
traceparent;网关、模型服务和搜索工具延续同一 trace,排障时能看到延迟发生在排队、首 token 还是工具调用。能设计 token 延迟、工具成功率和成本指标。
相关答案: 指标要有清晰起止点和维度:首 token 延迟从请求发出到首个可展示 token,完整延迟到结束;工具成功率区分成功、业务拒绝、超时和取消;成本结合模型、输入输出 token 与重试次数。应同时看分位数而非只看平均值。
具体例子: 仪表盘展示不同模型的 TTFT P50/P95、按工具分类的成功率和单会话成本;一次用户主动取消不应被误算成工具故障。
原理讲解
Core Web Vitals 衡量加载、交互和视觉稳定性。它们不是唯一指标,但能帮助团队建立共同语言。定位性能问题要依赖 Performance、Memory、Profiler 和真实用户监控,而不是只凭经验猜测。
AI 前端的高频 token 更新不能每个 chunk 都触发 React 整树渲染。使用外部 store 和不可变快照,让 React 只在快照变化时同步。监控还需要记录首 token 时间、完整响应时间、工具调用时间和重连次数。
端到端 Trace 要保留 request id,并在浏览器、网关、服务端和工具调用之间传递,才能回答一次 Agent 请求在哪一段变慢。
代码示例或模板
import { useSyncExternalStore } from "react";
function useChatSnapshot() {
return useSyncExternalStore(subscribeChat, getChatSnapshot, getChatSnapshot);
}
function ChatView() {
const snapshot = useChatSnapshot();
return <div>{snapshot.text}</div>;
}useSyncExternalStore 读取不可变快照,避免每个 token 都调用局部 setState。
AI Agent 概念对照
- token latency 对应前端性能指标。
- tool success rate 对应业务可观测性。
- session trace 对应端到端追踪。
- 流式重连对应网络稳定性。
面试追问
1. LCP、INP、CLS 分别说明什么问题?
查看深度解析
标准回答: LCP 衡量主要内容的加载呈现,INP 衡量用户交互到下一次绘制的响应性,CLS 衡量意外布局偏移和视觉稳定性。当前推荐以真实用户第 75 百分位观察,良好阈值分别是 LCP 不超过 2.5s、INP 不超过 200ms、CLS 不超过 0.1。
原理展开: 三者是共同语言,不覆盖所有体验;INP 需要真实交互,实验室通常用 TBT 辅助而不能等同替代。
工程示例: 大图慢影响 LCP,点击后同步解析大 JSON 影响 INP,图片未预留尺寸影响 CLS。
常见误区: 只看 Lighthouse 单次分数,或取平均值掩盖慢设备和长尾用户。
继续追问: 指标达标但用户仍觉得慢怎么办?
回答方向: 补充业务指标如搜索结果时间、首 token、任务完成和错误恢复,并按页面与用户群分段分析。
2. 一个页面很慢,如何用证据而不是经验定位?
查看深度解析
标准回答: 先定义“慢”的操作和指标,用 RUM 确认范围与分位数,再在可复现场景采集网络瀑布、Performance trace、框架 Profiler 和内存快照。根据时间线判断瓶颈属于网络、JavaScript、布局绘制还是后端。
原理展开: 先建立基线和假设,每次只改一个因素并复测;实验室证据解释机制,真实用户数据证明影响面。
工程示例: INP P75 变差后按路由和设备分组,发现低端机点击筛选触发 180ms 排序;火焰图定位具体函数,再移到 worker 或服务端。
常见误区: 一上来拆包、加 memo 或升级框架,没证明它位于关键路径;优化后也不比较指标。
继续追问: 无法在本地复现怎么办?
回答方向: 增加长任务、资源时序和 trace 采样,记录匿名化设备与功能维度,使用生产回放 fixture 而非收集敏感内容。
3. 高频 token 更新为什么不能每个 chunk 都触发整树 render?
查看深度解析
标准回答: chunk 频率可能远高于屏幕刷新率,每次在根状态更新会重复调度、reconcile 和提交,挤占输入、滚动与绘制时间。应按帧合并 token,并让消息组件订阅局部快照。
原理展开: 即使框架有自动批处理,也不保证跨所有网络任务按体验需要合并;状态边界和选择器比简单 memo 更重要。
工程示例: runtime 每个 delta 更新 buffer,每 16ms 最多发布一次;完成、错误和取消事件立即 flush。
常见误区: 为减少 render 直接每秒更新一次,导致输出明显迟钝;优化目标是控制提交频率而不是牺牲首 token。
继续追问: 如何证明优化有效?
回答方向: 比较提交次数、每次提交耗时、长任务、INP 和首/可见 token 延迟,并在低端设备压测。
4. 如何监控流式连接中断和重连?
查看深度解析
标准回答: 为每次连接记录 connection/request ID、开始、首事件、最后事件、正常结束、错误、断开原因、重连次数和退避时间;客户端和服务端用 trace ID 关联,并区分用户取消、网络切换、服务错误和代理超时。
原理展开: 只记录 error 数量无法判断影响时长与恢复效果;事件序号还能发现丢失和重复。
工程示例: 指标包含 unexpected_disconnect_rate、reconnect_success_rate、recovery_duration 和 duplicate_event_count,日志不保存完整 token 内容。
常见误区: 每次页面卸载都算故障,抬高错误率;或重连成功就忽略中间已产生的用户等待。
继续追问: 如何设置告警?
回答方向: 按版本、地区和网络分组,以基线和错误预算告警;同时观察重连成功率与恢复时长,避免单一固定阈值噪声。
5. 前端如何表达一次 Agent 请求的总延迟和分段成本?
查看深度解析
标准回答: 以用户发送为根 span,拆成排队、请求上传、模型首 token、模型生成、每次工具授权/执行、恢复和 UI 最终提交等子 span;总延迟按关键路径计算,成本记录模型 token、工具费用和重试。
原理展开: 并行工具耗时不能简单相加,用户感知延迟与资源总成本是两个维度。所有层传播统一 trace context 与稳定 ID。
工程示例: Trace 显示总计 8s,其中首 token 1.2s,两个并行工具关键路径 3s,生成 3.8s;成本面板另列输入输出 token 和搜索调用次数。
常见误区: 只记录请求开始结束,无法定位;或把浏览器与服务端时钟直接相减而未使用同一 trace 的 duration。
继续追问: 哪些数据不应进入 trace?
回答方向: 原始 prompt、token、密钥、完整文件路径和敏感工具参数默认不进属性,只记录大小、类型、哈希或脱敏摘要。
实践任务
为一个 AI 聊天页加入性能埋点,记录首屏、token 到达、工具状态、错误和重连,并输出可解释的 Trace。
验收标准
- 能回答一次请求在哪一段变慢。
- token 更新不触发整树渲染。
- 监控数据能区分用户取消、网络失败和模型失败。