编程进阶网 编程进阶网
首页
  • 计算机原理
  • 操作系统
  • 网络协议
  • 数据库原理
  • 面向对象
  • 设计原则
  • 设计模式
  • 系统架构
  • 性能优化
  • 编程原理
  • 方案设计
  • 稳定可靠
  • 工程运维
  • 基础认知
  • 线性结构
  • 树与哈希
  • 工业级实现
  • 算法思想
  • 实战与综合
  • 算法题考核
  • C语言入门
  • C综合案例
  • C专栏博客
  • C标准集库
  • C++入门教程
  • C++综合案例
  • C++专栏博客
  • C++开发技巧
  • Java入门教程
  • Java综合案例
  • Java专栏博客
  • Go入门教程
  • Go综合案例
  • Go专栏博客
  • Go开发技巧
  • JavaScript入门
  • JavaScript高级
  • Android库解读
  • Android专栏
  • Android智能硬件
  • iOS ObjC入门
  • iOS Swift入门
  • iOS入门精通
  • Web之Html手册
  • Web之TypeScript
  • Web之Vue高级进阶
  • Linux之QML入门
  • Linux之QT核心库
  • Linux实践开发
  • Python教程
  • Shell&Bash教程
  • 工具脚本
  • 自动化脚本
  • 质量保障
  • 产品思考
  • 软实力
  • 开发流程
  • Git应用
  • 技术模版
  • 技术规范
  • Markdown
  • Mermaid
  • 开源协议
  • JSON工具
  • 文本工具
  • 图片处理
  • 文档转化
  • 代码压缩
  • 关于我
  • 自我精进
  • 职场管理
  • 职场面试
  • 心情杂货
  • 友情链接

杨充

专注编程 · 终身学习者
首页
  • 计算机原理
  • 操作系统
  • 网络协议
  • 数据库原理
  • 面向对象
  • 设计原则
  • 设计模式
  • 系统架构
  • 性能优化
  • 编程原理
  • 方案设计
  • 稳定可靠
  • 工程运维
  • 基础认知
  • 线性结构
  • 树与哈希
  • 工业级实现
  • 算法思想
  • 实战与综合
  • 算法题考核
  • C语言入门
  • C综合案例
  • C专栏博客
  • C标准集库
  • C++入门教程
  • C++综合案例
  • C++专栏博客
  • C++开发技巧
  • Java入门教程
  • Java综合案例
  • Java专栏博客
  • Go入门教程
  • Go综合案例
  • Go专栏博客
  • Go开发技巧
  • JavaScript入门
  • JavaScript高级
  • Android库解读
  • Android专栏
  • Android智能硬件
  • iOS ObjC入门
  • iOS Swift入门
  • iOS入门精通
  • Web之Html手册
  • Web之TypeScript
  • Web之Vue高级进阶
  • Linux之QML入门
  • Linux之QT核心库
  • Linux实践开发
  • Python教程
  • Shell&Bash教程
  • 工具脚本
  • 自动化脚本
  • 质量保障
  • 产品思考
  • 软实力
  • 开发流程
  • Git应用
  • 技术模版
  • 技术规范
  • Markdown
  • Mermaid
  • 开源协议
  • JSON工具
  • 文本工具
  • 图片处理
  • 文档转化
  • 代码压缩
  • 关于我
  • 自我精进
  • 职场管理
  • 职场面试
  • 心情杂货
  • 友情链接
  • README
  • 性能优化实践

    • README
    • 公共方法论

      • 性能工程总论原理
        • 01.为什么需要"性能工程"
          • 1.1 经验主义的困境
          • 1.2 工程化的三个支柱
          • 1.3 本专栏的承诺
        • 02.性能的第一性原理
          • 2.1 性能本质:资源 × 时间 × 流水线
          • 2.2 三种"慢"的物理来源
          • A. 资源不足(Saturation)
          • B. 资源使用低效(Inefficiency)
          • C. 流水线阻塞(Stall)
          • 2.3 用户感知的非线性
          • 2.4 不可能三角
        • 03.跨平台统一抽象
          • 3.1 四层抽象模型
          • 3.2 平台差异的本质:实现而非原理
          • 3.3 跨平台映射表
        • 04.性能工程方法论
          • 4.1 四步归因法
          • 4.2 求证闭环
          • 4.3 优化的优先级判定
        • 05.性能工程的常见误区
          • 5.1 均值陷阱
          • 5.2 微优化先于架构优化
          • 5.3 把"忙"当作"慢"
          • 5.4 过早优化与过晚优化
        • 06.阅读路径与本专栏使用
          • 推荐阅读顺序
          • 各章节交叉引用约定
          • 一句话总结
      • 跨平台指标体系
      • 性能求证方法论
      • 数据采集与观测
      • 归因方法与火焰图
      • 性能预算防劣化
      • 性能体系全景图
      • 性能优化误区集
    • 体系建设篇

    • 资源专项篇

    • 流水线专项

    • 业务专项篇

    • 交付防御篇

  • 程序编程原理

  • 稳定性与可靠性

  • 工程化与运维

  • 方案设计思想

  • 专栏
  • 性能优化实践
  • 公共方法论
杨充
2026-05-27
目录

性能工程总论原理

# 性能工程总论与第一性原理

📊 学习成本预估 | 难度:⭐⭐⭐⭐⭐(5/5)| 阅读:约 25 分钟 | 实操:无(仅阅读) 🔗 前置阅读:— | ➡️ 后续延伸:卷零·02-06

本文是《性能优化实践》专栏的"宪法"。后续所有主题(CPU、内存、渲染、启动、网络…)都基于本文定义的模型与术语展开。如果你只读一篇,请读这一篇。

# 目录介绍

  • 01.为什么需要"性能工程"
    • 1.1 经验主义的困境
    • 1.2 工程化的三个支柱
    • 1.3 本专栏的承诺
  • 02.性能的第一性原理
    • 2.1 性能本质:资源 × 时间 × 流水线
    • 2.2 三种"慢"的物理来源
    • 2.3 用户感知的非线性
    • 2.4 不可能三角
  • 03.跨平台统一抽象
    • 3.1 四层抽象模型
    • 3.2 平台差异的本质:实现而非原理
    • 3.3 跨平台映射表
  • 04.性能工程方法论
    • 4.1 四步归因法
    • 4.2 求证闭环
    • 4.3 优化的优先级判定
  • 05.性能工程的常见误区
    • 5.1 均值陷阱
    • 5.2 微优化先于架构优化
    • 5.3 把"忙"当作"慢"
    • 5.4 过早优化与过晚优化
  • 06.阅读路径与本专栏使用

# 01.为什么需要"性能工程"

# 1.1 经验主义的困境

在没有方法论之前,绝大多数性能优化呈现以下症状:

  • "把这段代码改成异步就好了" —— 异步是手段,不是结论;何时该同步、何时该异步,取决于关键路径分析。
  • "换个图片库可能更快" —— 没有度量基线,"更快"是错觉。
  • "我们的 App 启动 1.2 秒,挺快的了" —— 这是均值还是 P95?冷启动还是温启动?哪一档机型?

经验主义的三个根本缺陷:

  1. 无度量 —— 凭直觉判断快慢,结论不可证伪。
  2. 无归因 —— 只看到症状(卡、慢、崩),看不到资源 / 时间 / 流水线层面的因果链。
  3. 无验证 —— 修改后是否真的变好了?是否引入了新副作用?没有对照实验。

一句话:经验主义优化的是"我感觉",工程化优化的是"我证明"。

# 1.2 工程化的三个支柱

性能工程(Performance Engineering)是一门可度量、可推导、可复现的工程学科,其三个支柱:

支柱 核心问题 对应章节
可观测性(Observability) 我能看到什么? 04.数据采集与观测
可归因性(Attributability) 看到了,能解释为什么吗? 05.归因方法与火焰图
可验证性(Verifiability) 解释了,能证明吗? 03.性能求证方法论

性能工程不是工具集合,而是一套让性能问题从"玄学"变为"科学"的范式。

# 1.3 本专栏的承诺

读完本专栏,你应当能够:

  1. 用同一套模型和指标讨论 Android / iOS / Web / 嵌入式 / 桌面的性能问题,不再被平台 API 的差异困扰。
  2. 拿到一个性能问题时,能快速回答:
    • 它属于哪一层(系统 / 运行时 / 应用 / 体感)?
    • 它的瓶颈是哪种资源(CPU / 内存 / IO / GPU / 网络)?
    • 它在流水线的哪一段被阻塞?
  3. 设计可证伪的优化实验,并用统计方法判定"优化是否真的有效"。
  4. 建设线上可观测 + 线下可防御的性能保障体系。

# 02.性能的第一性原理

# 2.1 性能本质:资源 × 时间 × 流水线

任何"慢",都可以拆解为下面这个等式:

完成一项任务所需的墙钟时间
  = Σ(每段操作的执行时间)
  + Σ(每段操作的等待时间)
  - 重叠执行节省的时间(流水线并行)
1
2
3
4

进一步抽象,性能问题恒等于以下三者之一:

                      ┌──────────────┐
                      │  资源不足    │  ← 总量供给问题
                      │ (CPU/MEM/IO) │
                      └──────────────┘
   性能问题  =   ──┬──┌──────────────┐
                   │   │ 资源使用低效 │  ← 算法/数据局部性/不必要计算
                   │   └──────────────┘
                   │   ┌──────────────┐
                   └──▶│ 流水线阻塞   │  ← 串行依赖/锁/上下文切换
                       └──────────────┘
1
2
3
4
5
6
7
8
9
10

之所以称为"第一性原理",是因为任何平台、任何语言、任何架构下的性能问题,都不会逃出这三类。

# 2.2 三种"慢"的物理来源

# A. 资源不足(Saturation)

  • 表现:CPU 利用率 100%、内存接近物理上限、磁盘 / 网络队列堆积。
  • 度量信号:USE 模型中的 Saturation(饱和度)。
  • 治理思路:扩容(不可能时)→ 限流 → 降级 → 优先级调度。

# B. 资源使用低效(Inefficiency)

  • 表现:CPU 利用率不高,但完成相同任务消耗的指令数多;内存频繁 GC;缓存命中率低。
  • 度量信号:IPC(每周期指令数)、Cache Miss Rate、GC 频率与停顿。
  • 治理思路:算法复杂度 → 数据结构 → 数据局部性(cache friendly)→ 减少冗余计算。

# C. 流水线阻塞(Stall)

  • 表现:CPU 闲、内存够、IO 不忙,但用户感觉就是卡。本质是关键路径上有人在等。
  • 度量信号:主线程 / 关键线程的 off-CPU time、锁竞争时间、IO Wait 时长。
  • 治理思路:关键路径分析 → 解依赖 → 并行化 → 异步化 → 预取 / 预计算。

⚠️ 这是最容易被忽视的一类问题。很多 App 看起来 CPU 不高、内存正常,但用户依然觉得卡,根本原因是"在错误的时机做了正确的事"。

# 2.3 用户感知的非线性

性能优化的目的不是让某个数字变小,而是让用户感觉变好。两者并非线性映射:

场景 关键阈值(业界共识) 物理依据
即时响应 < 100ms 人类大脑感知"因果连续"的极限
流畅动画 每帧 < 16.67ms(60Hz)/ < 8.33ms(120Hz) 视觉残留 + 显示器刷新周期
操作反馈 < 1s 用户保持注意力、不切换任务的极限
等待忍耐 < 10s 超过则需 Loading / 进度条
启动 冷启 < 2s 优秀,> 5s 不可接受 Google Play Vitals / Apple HIG

关键洞察:

  • 把启动从 5s 优化到 3s,用户感受是"质变"。
  • 把启动从 1.5s 优化到 1.2s,用户几乎感知不到。
  • 因此优化的 ROI 高度依赖用户当前所处的感知区间。

# 2.4 不可能三角

性能优化无法同时最大化以下三者,必须取舍:

            性能(速度)
               △
              ╱ ╲
             ╱   ╲
            ╱     ╲
           ╱       ╲
          ╱         ╲
   资源占用 ──────── 功能完整度
   (内存/包体)        (能力/灵活性)
1
2
3
4
5
6
7
8
9

举例:

  • 预加载提速 → 牺牲内存与流量。
  • 图片高画质 → 牺牲带宽与解码 CPU。
  • 极致压缩 → 牺牲运行时解压 CPU。
  • 强缓存 → 牺牲数据新鲜度(功能完整度)。

设计性能方案时,必须显式声明在不可能三角中取的位置和理由。

# 03.跨平台统一抽象

# 3.1 四层抽象模型

无论 Android / iOS / Web / 嵌入式,都可以套用以下四层:

┌──────────────────────────────────────────────────────┐
│  L4 体感层:用户感知(流畅 / 快 / 稳)                │  ← 优化的最终目标
├──────────────────────────────────────────────────────┤
│  L3 应用层:业务代码 / UI 框架 / 状态管理            │  ← 90% 的优化战场
├──────────────────────────────────────────────────────┤
│  L2 运行时:VM / GC / 渲染管线 / 调度器              │  ← 理解原理的关键
├──────────────────────────────────────────────────────┤
│  L1 系统层:OS 内核 / CPU / 内存 / IO / 网络         │  ← 性能的物理上限
└──────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9

优化原则:

  • 自顶向下分析:从 L4 现象出发,向下定位到具体层。
  • 自底向上优化:先确保 L1/L2 没瓶颈,再优化 L3 业务逻辑。
  • 跨层耦合是最大坑:L3 的一行代码可能引发 L2 GC 风暴或 L1 IO 阻塞。

# 3.2 平台差异的本质:实现而非原理

不同平台的"性能差异",几乎全部来自实现策略而非原理。例如:

概念 Android iOS Web 嵌入式(Linux/RTOS)
主线程不能阻塞 UI Thread / Looper Main RunLoop Main JS Thread UI Task / Render Task
内存回收 ART GC(分代+并发) ARC(引用计数) V8 GC(分代+增量) 手动 / 引用计数
渲染时钟 Choreographer / Vsync CADisplayLink / Vsync requestAnimationFrame 显示控制器 IRQ
任务调度 Handler / WorkManager GCD / NSOperation MessageLoop / setTimeout 任务队列 / RTOS 调度

关键认知:上面这些"差异"在原理层是同一件事 —— 任务通过队列被调度到合适的执行单元,受限于显示时钟与资源饱和度。学懂任意一端的原理,迁移到其他端只需要换 API 名称。

# 3.3 跨平台映射表

为方便后续章节引用,定义如下统一术语:

统一术语 含义 Android 对应 iOS 对应 Web 对应 嵌入式对应
主线程 UI / 关键路径执行单元 UI Thread Main Thread Main JS Thread UI Task
帧时钟 显示同步信号源 Vsync / Choreographer CADisplayLink rAF 显示 IRQ
任务队列 主线程消息队列 MessageQueue RunLoop sources Task Queue OS Queue
内存回收 释放无引用对象 ART GC ARC + dealloc V8 GC free / 引用计数
渲染管线 从数据到像素 Measure→Layout→Draw→Composite Layout→Display→Composite Style→Layout→Paint→Composite 自定义
采样器 性能数据采集源头 Tracepoint / perfetto os_signpost / Instruments Performance API ftrace / lttng

后续章节出现"主线程""帧时钟"等词时,默认指统一术语,再视情况下钻到平台特化。

# 04.性能工程方法论

# 4.1 四步归因法

任何性能问题的处理,都遵循同一闭环:

┌─────────┐  现象     ┌─────────┐  量化    ┌─────────┐  实验
│ 现象    │ ───────▶ │ 度量    │ ───────▶│ 归因    │ ──────┐
│Symptom  │          │Measure  │         │Attribute│       │
└─────────┘          └─────────┘         └─────────┘       │
     ▲                                                      │
     │              ┌─────────┐  对照                       │
     └─────────────│ 验证    │ ◀────────────────────────────┘
        反馈        │ Verify  │
                   └─────────┘
1
2
3
4
5
6
7
8
9

每一步的输入输出:

步骤 输入 输出 失败信号
现象 用户反馈 / 监控告警 可复现的最小场景 描述模糊、不可复现
度量 复现场景 数值化指标(带分布) 只有均值、没有分布
归因 度量数据 落到具体函数 / 系统调用 / 资源 停在"框架太慢"
验证 修改方案 修改前后的对照数据 没做 A/B、引入新问题

# 4.2 求证闭环

把上述四步细化为科研级别的求证流程(详见《03.性能求证方法论》):

1. 提出假设 H1:变更 X 会让指标 Y 改善 ΔY,置信区间 [a, b]
2. 设计实验:控制变量、对照组、样本量
3. 执行采样:足够多次,覆盖典型场景与极端场景
4. 统计判定:是否显著(p < 0.05)、效应量是否值得(ΔY > 阈值)
5. 边界探查:什么条件下结论不成立
6. 固化沉淀:加入回归基线 + 文档归档
1
2
3
4
5
6

本专栏的所有"建议"都按此流程产出,禁止出现"经验上一般这样做"。

# 4.3 优化的优先级判定

资源永远有限,必须用 ROI 排序优化任务:

ROI = (预期收益 × 影响用户比例) / (开发成本 × 风险系数)
1

落地为三象限决策:

维度 判定问题
收益 优化后 P95 / P99 改善多少?影响多少 DAU?业务指标(留存 / 转化)能涨多少?
成本 改动范围多大?需要多少端联调?是否需要重构?
风险 是否影响功能正确性?是否影响其他指标?回滚成本如何?

反模式:

  • ❌ 把均值从 200ms 优化到 180ms,但 P99 没变 —— 用户感知 0。
  • ❌ 启动优化 100ms 但牺牲了内存 30MB —— 在低端机加剧 OOM。
  • ❌ 优化了占比 5% 的代码路径,重构了 50% 的代码 —— 性价比极低。

# 05.性能工程的常见误区

# 5.1 均值陷阱

"我们的接口平均耗时 200ms,没问题。"

真相:均值掩盖长尾。如果 P99 是 5s,说明每 100 次请求就有一次"用户骂街"的体验。

正确做法:始终关注 P50 / P90 / P95 / P99 / P99.9 分布,并理解:

  • P50 看"普遍体验"
  • P95 看"差体验比例"
  • P99 / P99.9 看"灾难体验上限"

# 5.2 微优化先于架构优化

"我把这个 for 循环改成 while 了,应该会快一点。"

Amdahl 定律:优化 5% 代码路径,整体最多提升 5%;除非该路径被反复执行。

正确顺序:

1. 关键路径分析(找到 80% 时间花在哪 20% 代码上)
2. 架构 / 算法优化(量级变化:O(n²) → O(n log n))
3. 数据结构优化(缓存友好、减少分配)
4. 微优化(指令级、内联、SIMD)
1
2
3
4

# 5.3 把"忙"当作"慢"

"CPU 100% 了,肯定是 CPU 瓶颈。"

反例:

  • CPU 100% 但都在 IO Wait —— 是磁盘 / 网络瓶颈。
  • CPU 100% 但 IPC 极低 —— 是 cache miss / 内存带宽瓶颈。
  • CPU 利用率 30% 但用户卡 —— 主线程在等锁 / IO(Stall 类问题)。

正确做法:用 USE 三元组(Utilization / Saturation / Errors)+ on-CPU vs off-CPU 时间分解。

# 5.4 过早优化与过晚优化

Donald Knuth 的名言"过早优化是万恶之源"被严重断章取义。完整版是:

"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%."

正确判断:

  • 过早优化:在没有度量的情况下,对非关键路径做复杂优化。
  • 过晚优化:在架构定型后才发现性能问题,此时改动成本极高。
  • 正确做法:在架构阶段就预留性能预算(详见《06.性能预算防劣化》),在编码阶段持续度量。

# 06.阅读路径与本专栏使用

# 推荐阅读顺序

新手路径(L1→L2):
  本文 → 02.指标体系 → 04.采集原理 → 各资源专题(CPU/内存/渲染)

进阶路径(L2→L3):
  本文 → 03.求证方法论 → 05.归因方法论 → 启动/网络/卡顿等业务专题

架构路径(L3→L4):
  本文 → 06.性能预算与防劣化 → 01.APM 设计 → 18.稳定性专项
1
2
3
4
5
6
7
8

# 各章节交叉引用约定

后续章节遵循以下约定:

  • 涉及"指标"时,引用《02.跨平台指标体系》;
  • 涉及"实验设计"时,引用《03.性能求证方法论》;
  • 涉及"采集方式"时,引用《04.数据采集与观测》;
  • 涉及"归因路径"时,引用《05.归因方法与火焰图》;
  • 涉及"防劣化"时,引用《06.性能预算防劣化》。

# 一句话总结

性能优化的本质,是用第一性原理拆解问题,用度量替代直觉,用实验替代经验,用闭环替代救火。

上次更新: 2026/06/07, 10:26:12
README
跨平台指标体系

← README 跨平台指标体系→

最近更新
01
信号崩溃快速排查
06-15
02
CoreDump破案
06-15
03
perf火焰图实战
06-15
更多文章>
Theme by Vdoing | Copyright © 2019-2026 杨充 | MIT License | 桂ICP备2024034950号 | 桂公网安备45142202000030
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式