性能之巅

2024, Nov 10    
  • 性能优化方法:包括响应时间和吞吐量优化,以及基准测试、容量规划、垂直和水平扩展等方面的优化方法。
  • 系统架构设计:包括分层架构、微服务架构、事件驱动架构、云原生架构等,以及它们的优缺点和适用场景。
  • 操作系统和计算机体系结构:包括CPU、内存、缓存、磁盘、网络等硬件和操作系统相关的知识,以及如何优化它们的性能。
  • 数据库和存储系统:包括关系型数据库、NoSQL数据库、内存数据库、文件系统等,以及它们的优缺点和适用场景。
  • 分布式系统:包括分布式存储、分布式计算、分布式事务等,以及如何处理分布式系统中的并发和一致性问题。
  • 云计算和容器技术:包括公有云、私有云、混合云等云计算部署模型,以及Docker、Kubernetes等容器技术的基本概念和使用方法。
  • 网络和协议:包括TCP/IP协议、HTTP协议、WebSocket协议等,以及如何诊断和优化网络问题。
  • 性能工具和监控:包括负载测试工具、性能监控工具、日志分析工具等,以及如何使用这些工具来诊断和解决性能问题。
  • 安全和可靠性:包括如何保证系统的可用性、可靠性和安全性,以及如何应对各种安全和可靠性威胁。
  • DevOps和敏捷开发:包括DevOps和敏捷开发的基本概念、实践和工具,以及如何将它们与性能优化和系统设计相结合。

目录结构

第一部分:性能指标与性能分析

  • 第1章:性能指标和性能评估
  • 第2章:性能分析的基础
  • 第3章:性能基准测试

第一部分的重点是关于性能测量的基本原理和工具,涵盖以下几个方面:

  1. 性能测量的基本原理:Brendan Gregg在本书中介绍了性能测量的四个基本原则,即测量、分析、比较和验证。
  2. 性能测量的基本工具:本书介绍了多种性能观测工具,包括计数器、跟踪器和剖析器等。其中,计数器是内核维护的统计数据,可以用于对事件计数。
  3. 火焰图:本书介绍了火焰图作为一种常用的性能分析工具,可以用于可视化代码的执行过程,并识别瓶颈。
  4. 其他工具和技术:本书还介绍了其他性能观测工具和技术,如dtrace、perf等,并提供了相应的实例和使用方法。

第二部分:系统性能

  • 第4章:操作系统的性能
  • 第5章:存储系统的性能
  • 第6章:网络性能

第三部分:企业应用性能

  • 第7章:企业应用性能基础
  • 第8章:Java虚拟机性能
  • 第9章:数据库性能
  • 第10章:Web应用程序性能

第四部分:云计算性能

  • 第11章:云计算的性能挑战
  • 第12章:云服务的性能分析
  • 第13章:云应用程序性能

第五部分:性能优化

  • 第14章:系统和应用程序性能优化
  • 第15章:云环境中的性能优化

频次最高的10个分析工具或命令

  1. top:用于查看系统中运行的进程和资源占用情况的命令行工具。
  2. sar:系统活动报告工具,用于收集和报告系统资源使用情况的命令行工具。
  3. strace:用于跟踪进程系统调用和信号的命令行工具。
  4. tcpdump:用于捕获和分析网络数据包的命令行工具。
  5. Wireshark:网络协议分析工具,用于分析和调试网络通信的图形化工具。
  6. perf:Linux性能事件分析工具,用于分析CPU、内存和I/O等性能事件的命令行工具。
  7. lsof:列出打开文件的工具,用于显示系统中打开的文件和进程的命令行工具。
  8. ps:查看系统进程的命令行工具。
  9. iostat:输入/输出统计工具,用于监控系统磁盘和存储性能的命令行工具。
  10. vmstat:虚拟内存统计工具,用于监控系统内存和CPU使用情况的命令行工具。

第1章 综述

1.1 系统性能

(图 1.1 系统性能-通用软件栈)

系统性能:指计算机系统在特定工作负载下的表现,包括响应时间、吞吐量、资源利用率等指标。

  • 整个系统的研究:所有的硬件组件和整个软件栈。
  • 所有数据路径、软硬件上所有的事情都会影响性能。
  • 当讨论到系统性能,全栈表示所有事情,包括系统库及内核。

全栈(entire stack):在性能分析语境下,指从硬件到应用层的完整软件栈,包括:

  • 硬件层:CPU、内存、磁盘、网络
  • 操作系统层:内核、系统调用、文件系统
  • 运行时层:虚拟机、库函数
  • 应用层:应用程序代码

注意:有时”全栈”仅指应用程序环境,包括数据库、应用程序,以及网站服务器。

1.2 人员与职能

  • 一般人员配置都是兼职对性能问题的解决,这样出现问题需要很多职能的人协作解决。
  • 有的公司会请性能工程师(Performance Engineer),其主要任务就是维护系统性能。
    • 他们与多个团队协同工作
    • 对环境做全局性的研究
    • 执行一些对解决复杂性能问题至关重要的操作
    • 会开发更好的工具
    • 对整个环境做系统级分析(system-wide analysis)
    • 为容量规划(capacity planning)定义指标

性能工程师:专门负责系统性能优化和分析的专业人员,需要具备:

  • 系统级性能分析能力
  • 跨团队协作能力
  • 工具开发能力
  • 性能建模和容量规划能力
  • 性能工程师也有精细到应用程序(MySQL性能工程师、Java性能工程师等)的工种,通常他们在开始使用特定的应用程序工具之前,会做一些系统性能检查,但是有限。

1.3 性能领域的事情

(图 1.3 事情)

  1. 设置性能目标和建立性能模型
  2. 基于软件或硬件原型进行性能特征归纳
  3. 对开发代码进行性能分析(软件整合之前)
  4. 执行软件非回归性测试(软件发布前或发布后)
  5. 针对软件发布版本的基准测试
  6. 目标环境中的概念验证(Proof-of-concept)测试
  7. 生产环境部署的配置优化
  8. 监控生产环境中运行的软件
  9. 特定问题的性能分析
  • 1~5 是常见的软件开发过程,这个阶段经常缺失性能设计,从而导致6~9节点在客户环境中出现”未知”的性能问题。
  • 当没有性能设计参与的架构,后期出现的性能问题修复难度会越来越大。
  • 因为缺乏设计,所以没有目标,没有目标,监控就容易丢失重心。
  • 在设计阶段对开发软件的资源占用情况进行研究,得以进一步确认最初性能设计与性能目标的偏差程度。在部署后,监控资源的使用情况,可以在问题出现之前就被发现。

容量规划(Capacity Planning):指一系列事前行动,包括:

  • 预测未来资源需求
  • 评估当前系统容量
  • 规划系统扩展方案
  • 定义性能指标和阈值
  • 建立性能基线

1.4 视角

图 视角

负载分析(Workload Analysis):从上而下的分析方法,关注系统输入和应用程序响应。

  • 分析对象:请求、事务、用户操作
  • 关注指标:吞吐量、响应时间、错误率
  • 适用场景:应用性能问题诊断
  • 典型使用者:系统管理员、运维人员

资源分析(Resource Analysis):从下而上的分析方法,关注系统资源的使用情况。

  • 分析对象:CPU、内存、磁盘、网络等资源
  • 关注指标:使用率、饱和度、错误
  • 适用场景:容量规划、资源瓶颈识别
  • 典型使用者:开发人员、性能工程师

1.5 性能是充满挑战的

1.5.1 性能是主观的

  • 已经存在的客观事实,在没有明确的期望性能目标时,很难断定其“好”或“坏”。
  • 需要方法将性能客观化。

1.5.2 性能是复杂的

  • 系统的复杂性,组件的关联。
  • 常常缺少一个明确的分析起点。
  • 瓶颈往往是复杂的,看似解决了瓶颈,可能只是将瓶颈推向了系统的其他地方,从而导致整体系统性能没有提升。
  • 环境很难复现,或只能间歇式重现。

1.5.3 可能多个问题并存

  • 成熟的软件,即便是那些被认为拥有高性能的软件,也会有不少已知的但未被修复的性能问题。
  • 真正的任务不是寻找问题,而是辨别问题或者说是辨别哪些问题是最重要的。
  • 识别“最重要的”,意味着性能分析要对问题的重要程度进行“量化”(quantify)。
  • 理想情况:1. 量化问题 2. 估计每个问题修复后带来的增速。
  • 延时(latency)这个指标非常适合量化性能。

1.6 延时 Latency

延时(Latency):操作执行之前所花费的等待时间,或操作完成所需的总时间。

  • 延时 = 等待时间
  • 广义:所有操作完成的等待时间
  • 延时可以估计最大增速(maximum speedup)

延时的组成:

  • 服务时间:实际处理时间
  • 等待时间:排队等待时间
  • 传输时间:数据传输时间

最大增速(Maximum Speedup):通过消除延时所能获得的最大性能提升。如果某个操作有50%的时间在等待,理论上最多可以获得2倍的性能提升。

1.7 动态跟踪 dynamic tracing

动态跟踪(Dynamic Tracing):一种运行时性能分析技术,可以在不修改代码的情况下,在任意程序点插入探针(probe)来收集性能数据。

  • 动态跟踪可以从任意感兴趣的点测量延时(latency),并且提供数据以显示延时完整的分布情况。
  • dynamic tracing 可以把所有软件变得可以监控。
  • 可以在真实的生产环境中使用。
  • 比”内核分析”更方便的对延时建立测量监控。

Dtrace:由Sun Microsystems开发的动态跟踪框架,对用户态和内核态的软件都提供了静态跟踪和动态跟踪能力。

  • 静态跟踪:在编译时插入的探针
  • 动态跟踪:在运行时插入的探针
  • 支持多种语言:C、C++、Java、Python等

其他动态跟踪工具:

  • SystemTap:Linux平台的动态跟踪工具
  • eBPF:Linux内核的扩展Berkeley包过滤器,用于动态跟踪
  • perf:Linux性能分析工具,支持动态跟踪

1.8 云计算

云计算:通过网络提供计算资源(计算、存储、网络等)的服务模式。

云计算对性能的影响:

  • 虚拟化:通过虚拟化技术实现资源抽象,但会带来性能开销
  • 快速扩展:弹性扩展成为可能,可以快速响应负载变化
  • 容量规划:降低了容量规划的精度要求,可以按需扩展
  • 性能分析:性能分析需求要求更高,需要跨虚拟机、跨区域分析
  • 性能隔离(Performance Isolation):多租户环境下,租户间的性能隔离带来的性能影响

性能隔离:在多租户环境中,确保一个租户的性能不会受到其他租户的影响。包括:

  • CPU隔离:CPU时间片分配
  • 内存隔离:内存使用限制
  • I/O隔离:磁盘和网络带宽限制
  • 噪声邻居问题:其他租户的负载影响

1.9 案例

(待补充具体案例内容)


第2章 方法

2.1 术语

IOPS(Input/Output Operations Per Second):每秒的输入输出次数。对于硬盘,指每秒的读写次数。是数据传输的度量方式,常用于评估存储性能。随机I/O和顺序I/O的IOPS差异很大。

吞吐量(Throughput)

  • 数据传输速度(字节/秒或比特/秒)
  • 工作执行速率
  • 数据库下,指操作的速度(每秒操作数或每秒事务数)
  • 与延迟相关:高吞吐量可能意味着高延迟

响应时间(Response Time):一次操作从开始到完成的总时间。包括服务时间和等待时间。

延时(Latency)

  • 操作里用来等待服务的时间
  • 操作执行之前所花费的时间
  • 在某些情况,等同于响应时间
  • 是量化性能的重要指标

使用率(Utilization)

  • 对于服务所请求的资源,在给定时间区间内资源的繁忙程度
  • 基于时间:资源忙碌时间的百分比(U = B/T)
  • 基于容量:资源使用量占容量的百分比
  • 对于存储资源来说,使用率指的就是所消耗的存储容量(内存使用率)

饱和度(Saturation)

  • 某一资源无法满足服务的排队工作量
  • 资源过载的程度
  • 高饱和度会导致排队和延迟增加
  • 是USE方法的关键指标之一

瓶颈(Bottleneck)

  • 在系统性能里,瓶颈指的是限制系统性能的那个资源
  • 分辨和移除系统瓶颈是系统性能的一项重要工作
  • 瓶颈可能是CPU、内存、磁盘I/O、网络等
  • 解决一个瓶颈可能暴露另一个瓶颈

工作负载(Workload)

  • 系统的输入或者是对系统所施加的负载
  • 对于数据库来说,工作负载就是客户端发出的数据库请求和命令
  • 工作负载特征包括:请求类型、频率、数据量、访问模式等
  • 工作负载分析是性能分析的重要方法

缓存(Cache)

  • 用于复制或者缓冲一定量数据的高速存储区域
  • 目的是为了避免对较慢的存储层级的直接访问,从而提高性能
  • 出于经济考虑,缓存区的容量要比更慢一级的存储容量要小
  • 多层缓存:CPU缓存(L1/L2/L3)、内存缓存、磁盘缓存

2.2 模型

这些模型阐述了一些性能基本原则:

2.2.1 受测系统 SUT - System Under Test

受测系统(SUT, System Under Test):在性能测试中,被测试的系统或组件。

扰动(Noise):影响测试结果的非目标因素。

扰动会影响结果:

  • 扰动来源
    • 定时执行的系统活动(cron任务、系统维护)
    • 系统的其他用户
    • 其他的工作负载
    • 后台进程和服务
  • 云环境中的扰动:从单个客户的SUT的视角无法观察到物理宿主系统的其他活动(由其他租户引起的)
  • 减少扰动的方法
    • 在专用测试环境中测试
    • 多次运行取平均值
    • 使用统计方法过滤异常值

2.2.2 排队系统

排队系统(Queuing System):用于建模系统在负载下的行为,特别是当资源达到饱和时的性能表现。

排队系统的基本组成:

  • 到达过程:请求到达的规律(泊松分布、固定间隔等)
  • 服务过程:服务时间的分布(指数分布、固定时间等)
  • 服务台数量:并行处理能力
  • 队列容量:等待队列的大小

排队系统用于:

  • 预测系统在负载下的响应时间
  • 分析系统容量和瓶颈
  • 优化资源配置

详见 2.6.5 排队论

2.3 重要概念(概括)

概括描述,详细会在其他章节的分析部分。

2.3.1 延时

  • 操作执行之前所花费的时间。例如:这个操作用来数据传输,而这个操作执行之前必须先建立连接,这个建立连接的过程就是延时。
  • 性能问题可以用延时来进行量化和评级,因为延时都用的是相同的单位来表达。IOPS就不行。
  • 通过考量所能减少或移除的延时,预计的加速也可以计算出来。
  • 如果是100个网络I/O和50个磁盘I/O做选择,是一个非常复杂的选择,如果是100ms网络I/O,50ms的磁盘I/O就很简单。尝试将其他指标都转为延时或时间,这样更容易比较。

2.3.2 时间量级

用数字来作为时间的比较方法,同时可以用时间的长短经验来判断延时的源头。

事件 延时 相对时间比例
1个CPU周期 0.3ns 1s
L1缓存访问 0.9ns 3s
L2 2.8ns 9s
L3 12.9ns 43S
主存访问(从CPU访问DRAM) 120ns 6分
固态硬盘I/O(闪存) 50-150μs 2-6天
旋转磁盘I/O 1-10ms 1-12月
互联网:从旧金山到纽约 40ms 4年
互联网:从旧金山到英国 81ms 8年
互联网:从旧金山到澳大利亚 183ms 19年
TCP包重传 1-3s 105-317年
OS 虚拟化系统重启 4s 423年
SCSI命令超时 30s 3千年
硬件虚拟化系统重启 40s 4千年
物理系统重启 5m 32千年

CPU循环和延时 参考 第6章,第9章 互联网延时 参考第10章

2.3.3 权衡三角

权衡三角(Trade-off Triangle):性能优化中常见的三个维度之间的权衡关系。

常见的权衡关系:

  1. CPU与内存
    • 内存缓存数据结果,降低CPU的使用
    • 在CPU充足的情况下,CPU可以压缩数据来降低内存的使用
  2. 延迟与吞吐量
    • 批量处理可以提高吞吐量,但会增加延迟
    • 实时处理可以降低延迟,但吞吐量可能下降
  3. 成本与性能
    • 更好的硬件提供更好的性能,但成本更高
    • 软件优化可以提升性能,但开发成本增加

文件系统记录尺寸(或块的的大小):小的记录尺寸,接近应用程序I/O大小,随机I/O工作负载会有更好的性能,程序运行的时候能更充分地利用文件系统的缓存。选择大的记录尺寸能提高流的工作负载性能,包括文件系统的备份。

网络缓存尺寸:小的网络缓存尺寸会减小每一个连接的内存开销,有利于系统扩展,大的尺寸能提高网络的吞吐量。

2.3.4 调整的影响

  • 性能调整发生在越靠近工作执行的地方效果最显著。
  • 应用程序层级的调整,可能通过消去或减少数据查询获得很大的性能提升(例如,20倍)。
  • 存储设备层级的调整,可以精简或提高存储I/O,但是性能提升的大头在更高层级的系统栈代码-,所以调整得到的性能提升有限,时百分比量级(例如,20%)

调整事例

层级 调优对象
应用程序 执行的数据库请求
数据库 数据库表布局、索引、缓冲
系统调用 内存映射、读写、同步或异步I/O 标志
文件系统 记录尺寸、缓存尺寸、文件系统可调参数
存储 RAID级别、磁盘类型和数目、存储可调参数
  • 在应用程序层级的调整效果最显著,但不是观测效果最显著的层级。
  • 数据查询慢要从其花费的CPU时间、文件系统和所执行的磁盘I/O方面来考察最好。
  • 操作系统的性能分析能辨别出来的不仅是操作系统层级的问题,还有应用程序层级的问题,在某些情况下,甚至要比应用程序视角还简单。

2.3.5 合适的层级

不同的公司和环境对性能有着不同的需求,这取决于性能技术投入的投资回报率(ROI)。 例如:有的公司(纽约交易所与伦敦交易所)会投入3亿美金建立横跨大西洋的光缆,是为了减少6ms的的传输延时。

2.3.6 性能建议的时间点

性能配置不是所有时间点都有效。无法一劳永逸。

2.3.7 负载 vs.架构

图 性能差可能是来自软件配置和硬件,也有可能是架构问题,此外还有可能是太多的负载,而导致了排队和长延时。

2.3.8 扩展性

扩展性(Scalability):系统在负载增加时保持或提升性能的能力。

图 吞吐量 vs.负载

扩展性的三个阶段:

  1. 理想阶段(线性扩展)
    • 扩展性是线性变化的(吞吐量随着负载的增加而增加)
    • 资源充足,没有竞争
    • 性能随资源扩展成比例增长
  2. 拐点阶段(非线性扩展)
    • 拐点(Knee):性能由于资源限制停止线性增长的点
    • 当到达拐点的时候,资源的争夺开始影响性能
    • 此时扩展性将无法再保持线性发展,内聚性导致完成的工作变少而且吞吐量也减少了
    • 性能增长放缓,但仍能增长
  3. 饱和点(Saturation Point)
    • 当组件使用率达到100%或接近100%时,排队频繁且比较明显
    • 性能不再增长,甚至可能下降
    • 系统达到容量上限 例如,当程序是一个大量计算的应用程序(负载由线程承担),当cpu接近100%使用率时,延时增大,性能开始下降。当把x轴换成”CPU“,和上图的曲线会一致。

图 性能下降

性能的非线形变化,用平均响应时间或延时来表示。

  • 性能”快速”下降可能是由于内存的负载:当系统开始换页(或者使用swap)来补充内存的时候。
  • 性能”慢速”下降可能是由于CPU的负载。
  • 性能”快速“下降可能是由于磁盘I/O:随着负载(和磁盘使用率)的增加,I/O可能会排队。空闲的旋转的磁盘可能I/O服务响应时间约1ms,但是当负载增加,响应时间会变成10ms。可以查看2.6.5的模型,在M/D/1和60使用率情况下的表现。

如果资源不可用,应用程序开始返回错误,响应时间是线性变化的。例如:web服务器的503,而不是添加请求到排队队列中,这样的服务能用始终如一的响应时间来执行。

2.3.9 已知的未知

  • 已知的已知:有些东西你知道。例如:你知道你要检查性能指标,如CPU使用率,并且你也知道当前的均值是10%。
  • 已知的未知:有些东西你知道你不知道。例如:你知道你能用profiling检查是什么致使CPU忙碌,但你还没有去做这件事。
  • 未知的未知:有些东西你不知道你不知道。举个例子,你可能不知道设备终端可以消耗大量CPU资源,因此你对此并不做检查。

性能领域是”你知道的越多,你不知道的也就越多“。和学习系统是一样的原理:你了解的越多,就意识到”未知的未知“就越多,然后这些”未知的未知“就变成了”已知的未知“。

2.3.10 指标

IOPS 度量的是吞吐量,但只针对I/O操作(读取和写入)。

上下文很关键,上下文不同,定义可能会不同。

开销(Overhead):性能指标不是免费的,在某些时间后会消耗一些CPU周期来收集和保存指标信息。对目标的性能会有负面影响,这种影响被称为观察者效应(observer effect)。

观察者效应(Observer Effect):测量行为本身对被测量系统的影响。

  • 性能工具会消耗系统资源(CPU、内存、I/O)
  • 可能改变系统的执行路径(如添加日志、探针)
  • 需要权衡测量精度和系统影响

注意:这与海森堡测不准原理不同,后者描述的是对于互为共轭的物理量所能测量出的精度是有限的(如位置和动量)。(这通常与海森堡测不准原理混淆,后者描述的是对于互为共轭的物理量所能测量出的精度是有限的,诸如位置和动量。)”

问题:我们总是倾向于软件商提供的指标是经过仔细挑选,没有bug,并且具有很好的可见性。但事实上,这些指标可能是混淆的、复杂的、不可靠的、不精确的、甚至是错的(bug导致)。更多参见第4章。

2.3.11 使用率

使用率经常用于系统描述设备的使用情况。 使用率是基于时间或者容量的。 使用率告诉我们组件的忙碌程度。

基于时间

基于时间的使用率是使用排队理论做正式定义的。

例如 Gunther 97 : 服务器或资源繁忙时间的均值,相应的比例公式是 U = B/T U:使用率 T:观测周期 B:T时间内系统的繁忙时间

iostat(1)调用的指标%b,即忙碌百分比,能很好表现 “U=B/T”的本质。

组件A 100%使用率,并且该组件关联的系统性能严重下降,检查该系统的其他组件指标,确认该组件是不是成了整体的性能瓶颈。

有些组件在使用率100%的情况下,性能不会下降的很厉害。比如:能够并行地为操作提供服务的组件。

电梯在载人过程中(100%使用率),依然可以继续接收更多乘客。

100%忙碌的磁盘也能够接受并处理更多的工作,例如,通过把写入的数据放入磁盘内部的缓存中,稍后再完成写入,就能做到这点。通常存储序列运行在100%的使用率是因为其中的某些磁盘在100%忙碌时,序列中依然有足够的空闲磁盘来接受更多的工作。

基于容量

系统或组件(例如硬盘)都能够提供一定数量的吞吐。无论性能处于何种级别,系统或组件都工作在其容量的某一比例上。这个比例就称为使用率。

如果是容量的使用率,硬盘的100%意味不能接受更多工作。 如果是时间的使用率,硬盘的100%意味着时间上的忙碌,但可能接受更多任务。

100%忙碌(时间)不意味着100%的容量使用。

一般来说描述的使用率都是基于时间的。

非空闲时间

如何定义使用率,用上述定义可能会混淆,可尝试使用新词“非空闲时间”,这样描述更精准,但是没有普及。

2.3.12 饱和度

饱和度:随着工作量增加而对资源的请求处理超过资源所能处理的程度。 发生在100%使用率(基于容量)时,无法处理时,将进行排队。

当达到100%使用率时,随着负载增加,饱和度线性增加。 出现饱和度,意味着排队等待(延时),即是性能问题。

如果是基于时间的使用率达到100%不意味着会发生饱和度,这取决于资源处理任务的并行能力。

2.3.13 剖析 Profiling

剖析(Profiling):对目标对象的研究和理解。在计算机性能领域,指按照特定的时间间隔对目标(系统状态)进行采样,然后对采样进行研究。

Profiling的类型:

  1. CPU Profiling
    • 采样CPU执行状态
    • 识别热点函数和代码路径
    • 工具:perf、gprof、VisualVM
  2. 内存 Profiling
    • 分析内存分配和释放
    • 检测内存泄漏
    • 工具:valgrind、MAT、jmap
  3. I/O Profiling
    • 分析I/O操作
    • 识别I/O瓶颈
    • 工具:strace、ltrace、blktrace
  4. 时间 Profiling
    • 测量函数执行时间
    • 分析调用栈
    • 工具:dtrace、SystemTap

Profiling方法:

  • 采样(Sampling):定期采样,开销小但可能遗漏短时间事件
  • 插桩(Instrumentation):在代码中插入探针,准确但开销大
  • 事件跟踪(Event Tracing):记录所有相关事件,详细但数据量大

2.3.14 缓存

缓存被频繁用来性能提升。 把磁盘的块缓存在主内存(RAM)。 一般使用多层缓存。 CPU 主缓存(L3 < L2 < L1)。L2 和 L3 逐渐增加了容量及延时,这是一种经济上的权衡。

缓存性能重要指标,命中率

命中率 = 命中次数(hits) / ( hits + 未命中次数(misses))。

98%和99%之间的性能差异要比10%和11%之间的性能差异大很多。这取决于缓存的存储层次的速度差异,存储层级速度差异越大,曲线倾斜越陡峭。

缓存另一个指标,失效率:每分钟缓存失效的次数。 缓存失效和性能是线性。

例A: 工作负载A的命中率90%,失效率200/s。 工作负载B的命中率80%,失效率20/s。 哪个性能更好?

工作负载总的运行时间

运行时间= (命中率 * 命中延时)+(失效率 * 失效延时)

这里用的是平均命中延时和平均未命中延时,并且假定工作是串行发生的。

缓存替换算法

  • MRU(Most Recently Used,最近最常使用):保留最新使用的数据,适合访问模式具有时间局部性的场景。
  • LRU(Least Recently Used,最近最少使用):淘汰最近最少使用的数据,是最常用的缓存算法,适合大多数场景。
  • MFU(Most Frequently Used,最常使用):保留使用频率最高的数据,适合访问模式具有频率特征的场景。
  • LFU(Least Frequently Used,最不常使用):淘汰使用频率最低的数据,适合长期热点数据场景。
  • NFU(Not Frequently Used,不常使用):LRU的一个简化版本,使用计数器记录访问频率,花费不高但吞吐量稍小。
  • FIFO(First In First Out,先进先出):按进入顺序淘汰,实现简单但效果一般。
  • Random(随机):随机淘汰,实现最简单但效果最差。

缓存的热、冷和温

缓存的状态:

:命中率为0(或接近0,当它开始变暖的时候)。是空的,或填充的是无用数据。 :命中率超过99%。填充的是常用数据,或有着很高的命中率。 :填充了有用的数据,但命中率没有达到预想的高度。 热度:缓存的热度或冷度。提高热度的目的就是提高缓存的命中率。

如果缓存较大或下一级的存储较慢(或者两者皆有),会需要一段较长的时间来填充缓存使其变暖。

例如:

  • 128GB(DRAM),600GB(闪存)二级缓存,物理磁盘做存储。
  • 在随机读的负载下,磁盘 IOPS:2000次读。一次I/O(读):8KB。
  • 缓存变暖的速度仅有 16MB/s(2000 * 8KB)。
  • 两级缓存从冷开始,需要2小时来让DRAM变温,需要最少10小时让闪存变暖。
  • 2.28小时(128 * 1024 / 16 * 60 * 60 )达到 100%

2.4 视角

工作负载:在上而下 资源分析:在下而上

2.4.1 资源分析

  • 性能问题研究:看是否某特定类型资源的责任。
  • 容量规划:为设计新系统提供信息,或者对系统资源何时会耗尽做预测。

着重使用率的分析,判断资源是否已经处于极限或者接近极限。

适合的资源分析的指标如下:

  • IOPS
  • 吞吐量
  • 使用率
  • 饱和度

上述指标在给定负载的情况下,显示了使用程度及饱和程度(上述指标度量了在给定负载下资源所做的事情,显示资源的使用程度乃至饱和的程度)。

其他类型的指标,包括延时,也会被使用,来度量资源于给定工作负载的响应情况。

统计工具:vmstat、iostat、mpstat。

2.4.2 工作负载分析

检查应用程序的性能:所施加的工作负载和应用程序是如何响应的。

分析的对象如下:

  • 请求:所施加的工作负载
  • 延时:应用程序的影响时间
  • 完成度:查找错误

适合分析的指标:

  • 吞吐量
  • 延时

这些指标分别度量了请求量的大小和在其之下系统表现出的性能。

2.5 方法

讹方法(anti-methodologies)

系统性能分析和性能调整方法:

类型 方法
观测分析 街灯讹
观测分析 科学法
观测分析 工具法
观测分析 USE方法
观测分析 向下挖掘分析
观测分析 延时分析
观测分析 R方法
观测分析 事件跟踪
观测分析 基础线统计
实验分析 随机变动讹方法
实验分析 微基准测试
假设分析 责怪他人讹方法
观测与实验分析 Ad Hoc 核对清单法
信息收集 问题陈述法
生命周期分析 诊断循环
观测分析,容量规划 工作负载特征归纳
观测分析,容量规划 性能监控
观测分析,容量规划 静态性能调整
统计分析,容量规划 排队论
观测分析,调优 缓存调优
容量规划,调优 容量规划

2.5.1 街灯讹方法

这个方法用一类观测偏差来命名,这类偏差叫做街灯效应

一天晚上,一个警察看到一个醉汉在路灯下的地面上找东西,问他在找什么。醉汉回答说他钥匙丢了。警察看了看也找不到,就问他:“你确定你钥匙是在这儿丢的,就在路灯下?”醉汉说:“不,但是这儿的光是最亮的”。

这相当于查看top,不是因为这么做有道理,而是不知道什么使用其他工具。

2.5.2 随机变动讹方法

实验性质的讹方法。

操作:

  1. 任意选择一个项目做改动(例如,一项可变参数)。
  2. 朝某个方向做修改。
  3. 测量性能。
  4. 朝另一个方向修改。
  5. 测量性能。
  6. 步骤3或步骤5的结果是不是要好于基准值?如果是,保留修改并返回步骤1。

此方法非常耗时,而且不一定能长期有效,过程还可能产生更严重的问题。

2.5.3 责怪他人讹方法

步骤:

  1. 找到一个不是你负责的系统或环境的组件。
  2. 假定问题是与那个组件相关的。
  3. 把问题扔给负责那个组件的团队
  4. 如果证明错了,返回步骤1.

也许是网络问题。你能和网络团队确认一下是不是发生了丢包或其他事情么?

这个讹方法只是因缺乏数据而造成的无端臆想。

2.5.4 Ad Hoc 核对清单法

基于对该系统类型的经验和之前所遇到的问题。

例如:核对清单的一项:“运行iostat -x 1 检查await 列。如果该列在负载下持续超过10(ms),那么说明磁盘太慢或是磁盘过载。”

这类清单能在最短的时间内提供最大的价值,是即时建议而且需要频繁更新以保证反应当前状态。

清单需要写的清楚且规范,说明如何辨别每个问题和如何修复。

2.5.5 问题陈述法

询问客户以下问题来完成:

  1. 是什么让你认为存在性能问题?
  2. 系统之前运行得好吗?
  3. 最近有什么改动?软件?硬件?负载?
  4. 问题能用延时或者运行时间来表述吗?
  5. 问题影响其他的人和应用程序吗(或者仅仅影响的是你)?
  6. 环境是怎么样的?用了哪些软件和硬件?什么版本?什么样的配置?

询问上述问题过程中通常会立即指向一个根源和解决方案。 当遇到一个新的问题,首先应该使用这个方法。

2.5.6 科学法

假设和实验来研究未知问题

步骤:

  1. 问题
  2. 假设
  3. 预测
  4. 试验
  5. 分析

2.5.7 诊断循环

与科学法相似: 假设 -> 仪器检验 -> 数据 -> 假设

2.5.8 工具法

工具法是一种系统性的性能分析方法,通过使用各种性能分析工具来收集数据。

步骤:

  1. 列出可用的性能工具
  2. 对每个工具运行并收集数据
  3. 分析工具输出
  4. 识别性能问题

优点:

  • 系统全面
  • 可以发现多种问题

缺点:

  • 可能收集过多数据
  • 需要熟悉多种工具

2.5.9 USE方法

USE方法(Utilization, Saturation, Errors):一种系统性的性能分析方法,针对所有资源检查三个关键指标。

对于所有的资源,查看它的使用率、饱和度和错误。

USE方法的三个维度:

  1. Utilization(使用率)
    • 资源忙碌时间的百分比
    • 例如:CPU使用率80%,磁盘使用率60%
    • 高使用率可能表示瓶颈
  2. Saturation(饱和度)
    • 资源无法满足服务请求的程度
    • 例如:CPU队列长度、磁盘I/O等待队列
    • 高饱和度表示资源过载
  3. Errors(错误)
    • 资源发生的错误数量
    • 例如:网络丢包、磁盘I/O错误
    • 错误可能导致性能下降

USE方法的优势:

  • 系统全面:覆盖所有资源
  • 快速定位:优先检查USE指标异常的资源
  • 易于实施:大多数系统工具都提供这些指标

与工具法相反的是,USE方法列举的是系统资源而不是工具。

2.5.10 工作负载特征归纳

谁?:谁产生,用户ID? 远程IP地址?进程ID? 为什么?:会调用?代码路径、堆栈跟踪? 怎么?:怎么变化的?有规律? 什么?:特征是什么?IOPS?变动(标准方差)?

最好的性能来自消灭不必要的工作。

如果被识别的问题无法解决,那么可以用系统资源控制来限制它。

除了识别问题,工作负载特征归纳可以用于输入仿真基准设计。

通过此方法辨别负载问题,有利于将负载问题和架构问题区分。2.3有介绍。

此方法使用的工具视目标而定。比如:用户活动信息作为统计分析的来源。

2.5.11 向下挖掘分析

从高级指标开始,逐步深入分析,直到找到根本原因。

步骤:

  1. 从系统级指标开始(如CPU使用率)
  2. 识别异常的资源
  3. 深入分析该资源(如CPU -> 进程 -> 线程 -> 函数)
  4. 找到性能瓶颈

工具链:

  • 系统级:vmstat、iostat、mpstat
  • 进程级:top、pidstat
  • 函数级:perf、dtrace、strace

2.5.12 延时分析

专注于分析操作的延时,识别延时来源。

方法:

  1. 测量总延时
  2. 分解延时来源
  3. 量化各部分延时
  4. 优化最大延时来源

工具:

  • 应用级:APM工具
  • 系统级:perf、dtrace
  • 网络级:tcpdump、Wireshark

2.5.13 R方法

R方法(R Method):针对Oracle数据库的性能分析方法,由Cary Millsap开发。

R方法的核心思想:

  • R代表响应时间(Response Time)
  • 关注端到端的响应时间分解
  • 识别响应时间的主要组成部分

R方法的步骤:

  1. 测量总响应时间
  2. 分解响应时间(CPU时间、等待时间等)
  3. 识别最大的时间组成部分
  4. 优化最大的时间组成部分

R方法强调:

  • 响应时间比吞吐量更重要
  • 需要量化每个组成部分
  • 优化应该针对最大的时间组成部分

类似方法可以应用于其他数据库和系统。

2.5.14 事件跟踪

例如:tcpdump

tcpdump -ni eth0 -ttt

-ttt 输出所包含的DELTA时间,测量了包和包之间的时间。

2.5.15 基础线统计

建立性能基准线,用于对比和检测性能回归。

步骤:

  1. 在正常负载下测量性能指标
  2. 记录多个时间点的数据
  3. 建立统计模型(均值、标准差)
  4. 设置告警阈值

用途:

  • 性能回归检测
  • 容量规划
  • 性能趋势分析

2.5.16 静态性能调整

在系统设计阶段进行性能优化,而不是运行时调整。

方法:

  1. 选择合适的硬件
  2. 优化系统配置
  3. 选择合适的数据结构
  4. 优化算法

优点:

  • 避免运行时开销
  • 从根本上解决问题

2.5.17 缓存调优

优化缓存策略以提高命中率和性能。

方法:

  1. 分析缓存命中率
  2. 识别热点数据
  3. 调整缓存大小
  4. 优化缓存算法(LRU、LFU等)
  5. 多级缓存策略

指标:

  • 命中率
  • 失效率
  • 缓存大小
  • 缓存替换频率

2.5.18 微基准测试

测量的是施加了简单的人造工作负载的性能。

可以用于支持科学方法,将假设和预测放到测试中验证,或者作为容量规划的一部分来执行。

可以用微基准测试工具来测试工作负载并度量性能。

可以用负载生成器来产生负载,用标准的系统工具来测量性能。

最稳妥:微基准测试工具第一轮测试,标准系统工具第二轮测试(确认性能数据)

微基准测试例子:

  • 系统调用:针对fork()、exec()、open()、read()、close()。
  • 文件系统读取:从缓存过的文件读取,读取数据大小从1B变化到1MB。
  • 网络吞吐量:针对不同的socket缓冲区的尺寸测试TCP端对端数据传输。

测量完成大量上述这类操作所要的时间,然后计算均值(平均时间 = 运行时间/操作次数)

更多详见12章。

2.6 建模 (系统的分析模型)

可扩展性分析:建模可以用以研究当负载或资源扩展时性能会如何变化。可扩展性分析揭示拐点

拐点:性能由于资源限制停止线性增长的点。

性能评估方法(三大类):

  • 生产环境的观测:“测量”。
  • 实验性测试:”仿真“。
  • 分析建模。

以上三者至少择其二可让性能研究最为透彻。

  • 对现有系统:从测量开始,归纳负载特征和测量性能。
  • 系统没有生产环境负载/要测试的工作负载在生产环境不可见:工作负载仿真做测试。

详见“工作负载特征归纳”、“微基准测试”。

2.6.1 企业 vs.云

利用云计算技术,任意规模的环境都可以短期租用用于基准测试仿真。

2.6.2 可视化识别

数据可视化可以从其看到规律。

图 X是扩展的维度,Y轴是相应的性能(吞吐量、每秒事务数,等等)。

曲线类型如下:

  • 线性扩展:性能随资源扩展成比例增长。这种情况并非永久持续,但这可能是其他扩展情况的早期阶段。
  • 竞争:架构的某些组件是共享的,而且只能串行使用,共享资源的竞争会减少资源扩展的收益。
  • 一致性:要维持数据的一致性,传播数据变化的代价会超过扩展带来的好处。
  • 拐角:某个因素碰到了扩展的制约点,从而改变了扩展的曲线。
  • 扩展上限:到达了硬性的极限。极限可能是设备瓶颈。诸如总线或互联器件到了吞吐量的最大值,或者是一个软件设置的限制(系统资源控制)。

2.6.3 Amdahl 扩展定律

该定律主要考虑串行构成的工作负载(不能并行执行)。 该定律可以用于CPU、线程、工作负载等更多事务的扩展性研究。

公式:

C(N) = N / (1 + a(N - 1))

其中:

  • C(N):容量
  • N:扩展维度,CPU数量或用户负载
  • a:串行程度,即偏离线性扩展的程度,0 <= a <= 1

应用步骤:

  1. 测量或估计串行程度 a
  2. 计算不同 N 值下的容量 C(N)
  3. 识别拐点,即性能停止线性增长的点

当 a = 0 时,扩展是线性的;当 a > 0 时,串行部分限制了扩展性。

2.6.4 通用扩展定律

通用扩展定律(Universal Scalability Law, USL)是对Amdahl定律的扩展,考虑了竞争和一致性开销。

公式:

C(N) = N / (1 + σ(N - 1) + λN(N - 1))

其中:

  • σ:竞争系数(contention coefficient)
  • λ:一致性系数(coherency coefficient)

2.6.5 排队论

排队论(Queuing Theory):数学理论,用于建模系统在负载下的行为,特别是当资源达到饱和时。

排队论模型表示法:A/S/c

  • A:到达过程的分布(M=Markovian/泊松分布,D=Deterministic/固定,G=General/一般)
  • S:服务时间的分布(同上)
  • c:服务器数量

常见模型:

M/M/1 模型

  • 到达过程:泊松分布(Markovian),到达率λ
  • 服务时间:指数分布(Markovian),服务率μ
  • 服务器数量:1
  • 适用场景:单服务器系统,随机到达和随机服务时间

M/D/1 模型

  • 到达过程:泊松分布
  • 服务时间:固定(Deterministic)
  • 服务器数量:1
  • 适用场景:固定服务时间,如固定大小的数据包传输

M/M/c 模型

  • 到达过程:泊松分布
  • 服务时间:指数分布
  • 服务器数量:c(多个服务器)
  • 适用场景:多服务器系统,如负载均衡器后的多个服务器

排队论可以帮助预测:

  • 平均等待时间:请求在队列中的平均等待时间
  • 队列长度:队列中的平均请求数
  • 系统利用率对响应时间的影响:利用率越高,响应时间增长越快
  • 系统容量:在给定响应时间要求下的最大负载

重要公式(M/M/1):

  • 系统利用率:ρ = λ/μ(必须 < 1)
  • 平均队列长度:L = ρ/(1-ρ)
  • 平均等待时间:W = L/λ = ρ/(μ(1-ρ))

第3章 性能基准测试

3.1 基准测试概述

基准测试是性能评估的重要方法,用于:

  • 比较不同系统或配置的性能
  • 验证性能改进
  • 容量规划
  • 回归测试

3.2 基准测试类型

3.2.1 微基准测试

测量单个操作或小段代码的性能。

特点:

  • 简单、快速
  • 可能无法反映真实工作负载
  • 容易受到编译器优化影响

3.2.2 宏基准测试

测量完整应用程序或系统的性能。

特点:

  • 更接近真实场景
  • 复杂度高
  • 需要更多资源

3.2.3 合成基准测试

使用人工生成的工作负载。

3.2.4 回放基准测试

使用从生产环境捕获的真实工作负载。

3.3 基准测试方法

3.3.1 测试设计

  1. 明确目标:要测量什么?要比较什么?
  2. 选择工作负载:代表性、可重复性
  3. 控制变量:确保公平比较
  4. 多次运行:减少随机误差

3.3.2 测试执行

  • 预热阶段:让系统达到稳定状态
  • 测量阶段:收集性能数据
  • 冷却阶段:让系统恢复

3.3.3 结果分析

  • 统计方法:均值、中位数、百分位数
  • 可视化:图表、直方图
  • 比较分析:与基准线对比

3.4 基准测试陷阱

  1. 测试环境不匹配:硬件、软件、配置差异
  2. 工作负载不真实:无法代表实际使用
  3. 测量误差:工具开销、系统扰动
  4. 过早优化:基于不准确的基准测试优化
  5. 基准测试游戏:针对特定测试优化,实际性能未提升

3.5 基准测试工具

  • sysbench:数据库和系统性能测试
  • fio:存储I/O性能测试
  • iperf:网络性能测试
  • SPEC:标准化基准测试套件
  • TPC:事务处理性能委员会基准测试

第二部分 系统性能

第4章 操作系统的性能

4.1 CPU性能

4.1.1 CPU架构

  • 时钟频率(Clock Frequency):CPU执行指令的速率,单位Hz。频率越高,单核性能越强,但功耗也越高。

  • 指令级并行(Instruction-Level Parallelism, ILP)
    • 流水线(Pipeline):将指令执行分为多个阶段,不同指令在不同阶段并行执行
    • 超标量(Superscalar):每个时钟周期可以执行多条指令
    • 乱序执行(Out-of-Order Execution):不按程序顺序执行指令,提高指令级并行度
  • 缓存层次(Cache Hierarchy)
    • L1缓存:最快,容量最小(通常32KB-64KB),每个核心独享
    • L2缓存:较快,容量中等(通常256KB-512KB),每个核心独享
    • L3缓存:较慢,容量较大(通常几MB到几十MB),多个核心共享
  • 多核架构
    • SMP(Symmetric Multi-Processing):对称多处理,所有CPU核心平等访问内存
    • NUMA(Non-Uniform Memory Access):非统一内存访问,不同CPU核心访问不同内存区域的速度不同

4.1.2 CPU性能指标

  • 使用率(Utilization):CPU忙碌时间的百分比。100%表示CPU完全忙碌,但可能仍有处理能力(多核、超线程)。

  • 饱和度(Saturation):等待CPU的线程数。高饱和度表示CPU过载,线程需要等待。

  • 中断(Interrupt)
    • 硬件中断:由硬件设备触发(如网卡收到数据包)
    • 软件中断:由软件触发(如系统调用)
    • 中断处理会消耗CPU时间
  • 上下文切换(Context Switch):进程/线程切换时的开销,包括:
    • 保存当前进程状态
    • 加载新进程状态
    • 切换内存地址空间
    • 频繁的上下文切换会降低性能

4.1.3 CPU性能分析工具

  • top/htop:实时查看CPU使用情况
  • vmstat:系统整体统计
  • mpstat:多CPU统计
  • perf:性能事件分析
  • strace:系统调用跟踪

4.1.4 CPU性能优化

  • 减少不必要的计算
  • 优化算法和数据结构
  • 利用CPU缓存
  • 减少上下文切换
  • 使用CPU亲和性

4.2 内存性能

4.2.1 内存架构

  • 虚拟内存(Virtual Memory)
    • 为每个进程提供独立的地址空间
    • 地址空间大小通常远大于物理内存
    • 通过分页机制映射到物理内存
  • 物理内存(Physical Memory)
    • RAM(Random Access Memory):随机访问内存,速度快但易失
    • 交换空间(Swap Space):磁盘上的虚拟内存,速度慢但可持久化
  • 内存管理单元(MMU, Memory Management Unit)
    • 负责虚拟地址到物理地址的转换
    • 管理内存访问权限
    • 实现内存保护
  • 页面管理
    • 分页(Paging):将虚拟内存划分为固定大小的页面(通常4KB)
    • 分段(Segmentation):将内存划分为不同用途的段(代码段、数据段等)
    • 现代操作系统主要使用分页机制

4.2.2 内存性能指标

  • 使用率(Utilization):已用内存/总内存。高使用率可能导致换页。

  • 换页(Paging/Swapping)
    • 换出(Swap Out):将内存页面写入交换空间
    • 换入(Swap In):从交换空间读取页面到内存
    • 换页会显著降低性能(磁盘I/O比内存慢1000倍以上)
  • 缺页(Page Fault)
    • 软缺页(Minor Page Fault):页面在内存中但未映射,只需更新页表
    • 硬缺页(Major Page Fault):页面不在内存中,需要从磁盘读取
    • 硬缺页会导致性能下降
  • 内存泄漏(Memory Leak):程序分配内存后未释放,导致内存持续增长,最终可能耗尽系统内存。

4.2.3 内存性能分析工具

  • free:查看内存使用情况
  • vmstat:虚拟内存统计
  • sar:系统活动报告
  • valgrind:内存分析工具
  • pmap:进程内存映射

4.2.4 内存性能优化

  • 减少内存分配
  • 使用对象池
  • 优化数据结构大小
  • 减少内存碎片
  • 调整交换空间

4.3 文件系统性能

4.3.1 文件系统类型

  • ext4(Fourth Extended Filesystem)
    • Linux默认文件系统
    • 稳定可靠,适合大多数场景
    • 最大文件系统大小1EB,最大文件大小16TB
  • XFS(X File System)
    • 高性能文件系统,适合大文件和高并发
    • 支持大文件系统(最大8EB)和大文件(最大8EB)
    • 适合数据库、日志等场景
  • ZFS(Zettabyte File System)
    • 高级文件系统,集成了卷管理功能
    • 支持快照、克隆、数据完整性校验
    • 适合需要高级功能的场景
  • Btrfs(B-Tree File System)
    • 现代文件系统,支持写时复制(Copy-on-Write)
    • 支持快照、压缩、子卷
    • 仍在积极开发中

4.3.2 文件系统性能指标

  • IOPS:每秒I/O操作数
  • 吞吐量:数据传输速率
  • 延迟:I/O响应时间
  • 缓存命中率:页面缓存效果

4.3.3 文件系统性能分析工具

  • iostat:I/O统计
  • iotop:I/O top工具
  • lsof:列出打开的文件
  • strace:系统调用跟踪
  • blktrace:块设备跟踪

4.3.4 文件系统性能优化

  • 选择合适的文件系统
  • 调整挂载选项
  • 优化I/O调度器
  • 使用SSD
  • 调整页面缓存大小

4.4 进程和线程

4.4.1 进程模型

  • 进程:独立的执行单元
  • 线程:轻量级进程
  • 进程间通信(IPC):管道、信号、共享内存等

4.4.2 调度

  • 调度器:决定哪个进程运行
  • 优先级:进程优先级
  • 时间片:CPU时间分配
  • 负载均衡:多核负载分配

4.4.3 性能分析

  • ps:查看进程
  • top:实时进程监控
  • pidstat:进程统计
  • strace:系统调用跟踪

第5章 存储系统的性能

5.1 存储架构

5.1.1 存储层次

  1. CPU缓存:最快,容量最小
  2. 主内存(RAM):快速,易失性
  3. 固态硬盘(SSD):快速,非易失性
  4. 机械硬盘(HDD):较慢,非易失性
  5. 网络存储:远程访问

5.1.2 存储类型

  • DAS(Direct Attached Storage,直连存储)
    • 存储设备直接连接到服务器
    • 访问速度快,但扩展性差
    • 适合单服务器场景
  • NAS(Network Attached Storage,网络附加存储)
    • 通过网络(通常是以太网)提供文件级存储
    • 使用NFS、CIFS等协议
    • 易于管理和扩展
    • 适合文件共享场景
  • SAN(Storage Area Network,存储区域网络)
    • 通过网络(通常是光纤通道)提供块级存储
    • 高性能、低延迟
    • 适合数据库、虚拟化等高性能场景
  • 对象存储(Object Storage)
    • 以对象为单位存储数据,通过RESTful API访问
    • 高可扩展性、高可用性
    • 适合云存储、大数据、归档等场景
    • 典型产品:AWS S3、Azure Blob Storage

5.2 磁盘I/O性能

5.2.1 磁盘性能指标

  • IOPS:每秒I/O操作数
  • 吞吐量:数据传输速率(MB/s)
  • 延迟:I/O响应时间
  • 队列深度:待处理I/O数量

5.2.2 磁盘类型

  • HDD:机械硬盘,随机I/O较慢
  • SSD:固态硬盘,随机I/O快
  • NVMe:高速SSD接口

5.2.3 RAID

RAID(Redundant Array of Independent Disks):独立磁盘冗余阵列,通过多个磁盘组合提供更高的性能或可靠性。

RAID级别:

  • RAID 0(条带化)
    • 数据分散存储在多个磁盘
    • 性能最高(并行读写),无冗余
    • 任一磁盘故障会导致数据丢失
    • 适合对性能要求高、数据可重建的场景
  • RAID 1(镜像)
    • 数据完全复制到多个磁盘
    • 冗余高,任一磁盘故障不影响数据
    • 性能中等,写入需要同步到所有磁盘
    • 适合对可靠性要求高的场景
  • RAID 5(分布式奇偶校验)
    • 数据和奇偶校验信息分布在所有磁盘
    • 可容忍一个磁盘故障
    • 读写性能较好,但写入需要计算奇偶校验
    • 适合平衡性能和可靠性的场景
  • RAID 10(RAID 1+0)
    • 先做镜像(RAID 1),再做条带化(RAID 0)
    • 性能好,冗余高
    • 可容忍多个磁盘故障(只要不是同一镜像对)
    • 适合对性能和可靠性都要求高的场景
  • 其他RAID级别
    • RAID 6:类似RAID 5,但可容忍两个磁盘故障
    • RAID 50/60:RAID 5/6的条带化组合

5.3 存储性能分析

5.3.1 工具

  • iostat:I/O统计
  • iotop:I/O top
  • blktrace:块设备跟踪
  • fio:I/O基准测试

5.3.2 分析方法

  • USE方法:使用率、饱和度、错误
  • 工作负载特征:随机/顺序、读/写比例
  • 延迟分析:I/O延迟分布

5.4 存储性能优化

5.4.1 硬件优化

  • 使用SSD替代HDD
  • 增加磁盘数量(RAID)
  • 使用高速接口(NVMe)

5.4.2 软件优化

  • 调整I/O调度器
  • 使用异步I/O
  • 批量I/O操作
  • 预读和预写
  • 数据压缩

5.4.3 应用优化

  • 减少I/O操作
  • 批量处理
  • 缓存常用数据
  • 优化数据结构

第6章 网络性能

6.1 网络架构

6.1.1 网络层次

  • 物理层:物理连接
  • 数据链路层:帧传输
  • 网络层:IP路由
  • 传输层:TCP/UDP
  • 应用层:应用程序协议

6.1.2 网络设备

  • 网卡(NIC):网络接口
  • 交换机:数据包转发
  • 路由器:路由选择
  • 负载均衡器:流量分发

6.2 网络性能指标

6.2.1 带宽

  • 带宽:最大数据传输速率
  • 吞吐量:实际数据传输速率
  • 利用率:带宽使用百分比

6.2.2 延迟

  • RTT(Round-Trip Time,往返时间)
    • 数据包从发送到接收确认的总时间
    • 包括:发送时间 + 传播时间 + 处理时间 + 返回时间
    • 常用工具:ping命令测量RTT
  • 单向延迟(One-Way Latency)
    • 数据包单程传输时间
    • 需要时钟同步才能准确测量
    • 比RTT更精确,但测量更复杂
  • 抖动(Jitter)
    • 延迟的变化程度
    • 计算方式:连续数据包延迟的方差或标准差
    • 高抖动会影响实时应用(如视频、语音)

6.2.3 其他指标

  • 丢包率:丢失数据包比例
  • 错误率:错误数据包比例
  • 连接数:并发连接数

6.3 网络性能分析

6.3.1 工具

  • ping:测试连通性和延迟
  • traceroute:路由跟踪
  • tcpdump:数据包捕获
  • Wireshark:协议分析
  • iperf:带宽测试
  • netstat/ss:网络连接统计
  • iftop:网络流量监控

6.3.2 分析方法

  • 延迟分析:测量RTT和单向延迟
  • 吞吐量分析:测量实际带宽
  • 协议分析:分析TCP/UDP行为
  • 流量分析:分析数据流特征

6.4 TCP性能

6.4.1 TCP特性

  • 可靠传输(Reliable Delivery)
    • 通过确认机制保证数据到达
    • 丢失的数据包会重传
    • 保证数据顺序
  • 流量控制(Flow Control)
    • 使用滑动窗口机制
    • 接收方通过窗口大小控制发送方速率
    • 防止接收方缓冲区溢出
  • 拥塞控制(Congestion Control)
    • 慢启动(Slow Start):连接开始时指数增长窗口
    • 拥塞避免(Congestion Avoidance):检测到拥塞后线性增长窗口
    • 快速重传(Fast Retransmit):收到3个重复ACK立即重传
    • 快速恢复(Fast Recovery):快速重传后的恢复机制
  • 连接管理
    • 三次握手(Three-Way Handshake):建立连接(SYN、SYN-ACK、ACK)
    • 四次挥手(Four-Way Handshake):关闭连接(FIN、ACK、FIN、ACK)

6.4.2 TCP性能优化

  • 调整缓冲区大小:TCP窗口大小
  • 启用TCP优化选项:TCP_NODELAY、TCP_CORK
  • 使用连接池:复用连接
  • 批量传输:减少小包传输

6.5 网络性能优化

6.5.1 硬件优化

  • 使用高速网卡(10GbE、25GbE)
  • 网络设备升级
  • 减少网络跳数

6.5.2 软件优化

  • 调整内核参数
  • 使用高效协议(HTTP/2、QUIC)
  • 数据压缩
  • CDN加速

6.5.3 应用优化

  • 减少网络往返
  • 批量请求
  • 使用缓存
  • 异步I/O

第三部分 企业应用性能

第7章 企业应用性能基础

7.1 应用性能概述

企业应用性能涉及多个层面:

  • 应用程序代码
  • 运行时环境(JVM、.NET等)
  • 数据库
  • Web服务器
  • 操作系统

7.2 性能分析方法

7.2.1 应用性能监控(APM)

  • 代码级分析:函数调用、执行时间
  • 事务跟踪:端到端请求跟踪
  • 依赖分析:外部服务依赖

7.2.2 性能分析工具

  • Profiler:代码性能分析
  • APM工具:应用性能监控
  • 日志分析:分析应用日志
  • 指标收集:性能指标收集

7.3 常见性能问题

7.3.1 CPU问题

  • 算法效率低
  • 不必要的计算
  • 锁竞争

7.3.2 内存问题

  • 内存泄漏
  • 内存溢出
  • 频繁GC

7.3.3 I/O问题

  • 同步I/O阻塞
  • 数据库查询慢
  • 文件I/O慢

7.3.4 网络问题

  • 网络延迟高
  • 网络带宽不足
  • 连接数过多

7.4 性能优化策略

7.4.1 代码优化

  • 算法优化
  • 数据结构优化
  • 减少对象创建
  • 避免不必要的计算

7.4.2 架构优化

  • 缓存策略
  • 异步处理
  • 负载均衡
  • 数据库优化

7.4.3 配置优化

  • JVM参数调优
  • 数据库配置
  • Web服务器配置
  • 操作系统配置

第8章 Java虚拟机性能

8.1 JVM架构

8.1.1 内存模型

  • 堆(Heap):对象存储
    • 新生代(Young Generation)
    • 老年代(Old Generation)
  • 方法区(Metaspace):类元数据
  • 栈(Stack):线程栈
  • 程序计数器:指令位置

8.1.2 垃圾回收

垃圾回收(Garbage Collection, GC):自动管理内存的机制,自动回收不再使用的对象。

垃圾回收算法:

  • 标记-清除(Mark-Sweep)
    • 标记所有可达对象
    • 清除未标记的对象
    • 会产生内存碎片
  • 标记-复制(Mark-Copy)
    • 将存活对象复制到新空间
    • 适合新生代,回收效率高
    • 需要额外的内存空间
  • 标记-整理(Mark-Compact)
    • 标记存活对象后,移动对象消除碎片
    • 适合老年代
    • 回收效率较低但无碎片
  • 分代回收(Generational Collection)
    • 基于对象生命周期假设:大多数对象很快死亡
    • 新生代(Young Generation):新创建的对象,使用标记-复制
    • 老年代(Old Generation):长期存活的对象,使用标记-整理
    • 不同代使用不同的回收策略和频率

8.2 垃圾回收器

8.2.1 串行回收器

  • Serial GC:单线程,适合小应用
  • Serial Old GC:老年代串行回收

8.2.2 并行回收器

  • Parallel GC:多线程并行回收
  • Parallel Old GC:老年代并行回收

8.2.3 并发回收器

  • CMS(Concurrent Mark Sweep)
    • 并发标记清除,减少停顿时间
    • 适合对延迟敏感的应用
    • 会产生内存碎片,可能触发Full GC
  • G1(Garbage First)
    • 分代收集器,将堆划分为多个区域
    • 优先回收垃圾最多的区域
    • 可预测的停顿时间
    • 适合大堆内存(>4GB)
  • ZGC(Z Garbage Collector)
    • 低延迟回收器,停顿时间<10ms
    • 支持TB级堆内存
    • 并发标记、并发整理
    • 适合对延迟要求极高的应用
  • Shenandoah
    • 低延迟回收器,停顿时间与堆大小无关
    • 并发整理,减少停顿时间
    • 适合大堆内存和低延迟需求

8.3 JVM性能指标

8.3.1 内存指标

  • 堆使用率:堆内存使用百分比
  • GC频率:垃圾回收频率
  • GC时间:垃圾回收耗时
  • 对象分配率:对象创建速率

8.3.2 CPU指标

  • CPU使用率:JVM进程CPU使用
  • 线程数:活跃线程数
  • 锁竞争:锁等待时间

8.4 JVM性能分析工具

8.4.1 命令行工具

  • jps:查看Java进程
  • jstat:JVM统计信息
  • jmap:堆内存分析
  • jstack:线程堆栈分析
  • jinfo:JVM配置信息

8.4.2 可视化工具

  • jconsole:JVM监控
  • VisualVM:性能分析
  • JProfiler:商业分析工具
  • MAT:内存分析工具

8.4.3 性能分析

  • GC日志分析:分析垃圾回收行为
  • 线程转储分析:分析线程状态
  • 堆转储分析:分析内存使用

8.5 JVM性能优化

8.5.1 内存优化

  • 调整堆大小(-Xms, -Xmx)
  • 调整新生代大小(-Xmn)
  • 选择合适的GC算法
  • 优化对象生命周期

8.5.2 GC优化

  • 减少GC频率
  • 减少GC时间
  • 避免Full GC
  • 调整GC参数

8.5.3 代码优化

  • 减少对象创建
  • 使用对象池
  • 优化字符串操作
  • 避免不必要的同步

第9章 数据库性能

9.1 数据库架构

9.1.1 存储引擎

  • InnoDB:MySQL默认引擎,支持事务
  • MyISAM:MySQL旧引擎,不支持事务
  • PostgreSQL:对象关系数据库
  • MongoDB:文档数据库

9.1.2 索引

索引(Index):数据结构,用于快速定位数据,类似于书籍的目录。

索引类型:

  • B树索引(B-Tree Index)
    • 平衡树结构,支持范围查询
    • 适合大多数场景,MySQL InnoDB默认索引类型
    • 查询时间复杂度:O(log n)
  • 哈希索引(Hash Index)
    • 使用哈希表,支持等值查询
    • 查询速度快,但不支持范围查询
    • 适合等值查询频繁的场景
  • 全文索引(Full-Text Index)
    • 用于文本搜索
    • 支持关键词搜索、模糊匹配
    • 适合搜索引擎、内容管理系统
  • 复合索引(Composite Index)
    • 多列索引,按列顺序组织
    • 支持多列查询和前缀匹配
    • 需要注意列顺序,影响索引效果
  • 其他索引类型
    • 位图索引(Bitmap Index):适合低基数列
    • R树索引(R-Tree Index):用于空间数据
    • 倒排索引(Inverted Index):用于全文搜索

9.2 数据库性能指标

9.2.1 查询性能

  • 查询响应时间:查询执行时间
  • QPS:每秒查询数
  • TPS:每秒事务数
  • 慢查询:执行时间长的查询

9.2.2 资源使用

  • CPU使用率:数据库进程CPU使用
  • 内存使用率:缓冲池使用
  • I/O使用率:磁盘I/O
  • 连接数:数据库连接数

9.3 数据库性能分析

9.3.1 查询分析

  • EXPLAIN:查询执行计划
  • 慢查询日志:记录慢查询
  • 性能模式:MySQL性能监控
  • pg_stat_statements:PostgreSQL查询统计

9.3.2 监控工具

  • MySQL Workbench:MySQL管理工具
  • pgAdmin:PostgreSQL管理工具
  • Prometheus + Grafana:监控可视化
  • Percona Toolkit:MySQL工具集

9.4 数据库性能优化

9.4.1 查询优化

  • 使用索引
  • 优化SQL语句
  • 避免全表扫描
  • 使用连接池
  • 批量操作

9.4.2 索引优化

  • 创建合适的索引
  • 避免过多索引
  • 使用复合索引
  • 定期维护索引

9.4.3 配置优化

  • 调整缓冲池大小
  • 调整连接数
  • 优化查询缓存
  • 调整日志设置

9.4.4 架构优化

  • 读写分离
  • 分库分表
  • 缓存策略
  • 异步处理

第10章 Web应用程序性能

10.1 Web架构

10.1.1 典型架构

  • 前端:浏览器、CDN
  • Web服务器:Nginx、Apache
  • 应用服务器:Tomcat、Jetty
  • 数据库:MySQL、PostgreSQL
  • 缓存:Redis、Memcached

10.1.2 HTTP协议

  • HTTP/1.1
    • 传统协议,广泛使用
    • 每个连接只能处理一个请求-响应
    • 支持持久连接(Keep-Alive)
    • 头部未压缩,开销较大
  • HTTP/2
    • 多路复用(Multiplexing):单个连接可以并行处理多个请求
    • 头部压缩(Header Compression):使用HPACK算法压缩头部
    • 服务器推送(Server Push):服务器可以主动推送资源
    • 二进制分帧(Binary Framing):使用二进制格式,更高效
    • 显著提升性能,特别是高延迟网络
  • HTTPS(HTTP Secure)
    • HTTP over TLS/SSL
    • 提供加密和身份验证
    • 性能开销:TLS握手、加密解密
    • 现代Web应用的标准
  • WebSocket
    • 全双工通信协议
    • 建立连接后可以双向实时通信
    • 适合实时应用(聊天、游戏、监控等)
    • 比HTTP轮询更高效

10.2 Web性能指标

10.2.1 前端指标

  • 页面加载时间:页面完全加载时间
  • 首屏时间:首屏内容显示时间
  • DOM Ready:DOM就绪时间
  • 资源加载时间:CSS、JS加载时间

10.2.2 后端指标

  • 响应时间:服务器响应时间
  • 吞吐量:每秒请求数
  • 错误率:错误请求比例
  • 并发数:同时处理的请求数

10.3 Web性能分析

10.3.1 前端分析

  • Chrome DevTools:浏览器开发工具
  • Lighthouse:性能审计
  • WebPageTest:在线性能测试
  • RUM:真实用户监控

10.3.2 后端分析

  • APM工具:应用性能监控
  • 日志分析:分析访问日志
  • 性能测试:负载测试工具

10.4 Web性能优化

10.4.1 前端优化

  • 资源优化:压缩、合并、CDN
  • 代码优化:减少DOM操作、事件委托
  • 图片优化:压缩、懒加载、WebP
  • 缓存策略:浏览器缓存、HTTP缓存

10.4.2 后端优化

  • 代码优化:减少计算、异步处理
  • 数据库优化:查询优化、索引
  • 缓存策略:应用缓存、数据库缓存
  • 负载均衡:分发请求

10.4.3 网络优化

  • HTTP/2:使用新协议
  • CDN:内容分发网络
  • 压缩:Gzip、Brotli
  • 连接复用:Keep-Alive

第四部分 云计算性能

第11章 云计算的性能挑战

11.1 云计算特性

11.1.1 虚拟化

  • 虚拟机:完整操作系统虚拟化
  • 容器:轻量级虚拟化
  • 虚拟化开销:CPU、内存、I/O开销

11.1.2 多租户

多租户(Multi-Tenancy):多个租户(客户或应用)共享同一物理资源。

多租户的特点:

  • 资源共享:CPU、内存、网络共享,提高资源利用率
  • 性能隔离(Performance Isolation)
    • 租户间性能隔离,确保一个租户不影响其他租户
    • 通过资源限制(CPU配额、内存限制、I/O限制)实现
  • 噪声邻居(Noisy Neighbor)
    • 其他租户的负载影响当前租户的性能
    • 即使有资源限制,仍可能受到间接影响(如缓存竞争、网络拥塞)
    • 需要监控和告警机制

11.1.3 弹性扩展

  • 水平扩展:增加实例数量
  • 垂直扩展:增加实例规格
  • 自动扩展:根据负载自动调整

11.2 性能挑战

11.2.1 虚拟化开销

  • CPU虚拟化开销
  • 内存虚拟化开销
  • I/O虚拟化开销
  • 网络虚拟化开销

11.2.2 性能隔离

  • CPU调度影响
  • 内存竞争
  • I/O带宽竞争
  • 网络带宽竞争

11.2.3 网络延迟

  • 虚拟网络延迟
  • 跨区域延迟
  • 网络拥塞

11.2.4 存储性能

  • 网络存储延迟
  • 存储带宽限制
  • 存储IOPS限制

11.3 性能分析方法

11.3.1 监控

  • 云监控服务:AWS CloudWatch、Azure Monitor
  • APM工具:应用性能监控
  • 基础设施监控:Prometheus、Grafana

11.3.2 基准测试

  • 云环境基准测试
  • 性能对比测试
  • 容量规划测试

第12章 云服务的性能分析

12.1 云服务类型

12.1.1 计算服务

  • EC2/VM:虚拟机服务
  • Lambda/Functions:无服务器计算
  • 容器服务:Kubernetes、ECS

12.1.2 存储服务

  • 对象存储:S3、Blob Storage
  • 块存储:EBS、Azure Disk
  • 文件存储:EFS、Azure Files

12.1.3 数据库服务

  • 关系数据库:RDS、Azure SQL
  • NoSQL数据库:DynamoDB、Cosmos DB
  • 缓存服务:ElastiCache、Azure Cache

12.2 性能分析工具

12.2.1 云平台工具

  • CloudWatch:AWS监控
  • Azure Monitor:Azure监控
  • Stackdriver:GCP监控

12.2.2 第三方工具

  • Datadog:基础设施监控
  • New Relic:APM工具
  • Dynatrace:全栈监控

12.3 性能优化策略

12.3.1 实例选择

  • 选择合适的实例类型
  • 考虑CPU、内存、网络需求
  • 使用预留实例降低成本

12.3.2 架构优化

  • 使用CDN加速
  • 多区域部署
  • 负载均衡
  • 自动扩展

第13章 云应用程序性能

13.1 云原生应用

13.1.1 微服务架构

  • 服务拆分:按业务拆分服务
  • 服务通信:REST、gRPC、消息队列
  • 服务发现:服务注册与发现
  • 配置管理:集中配置管理

13.1.2 容器化

  • Docker:容器化技术
  • Kubernetes:容器编排
  • 容器优化:镜像大小、启动时间

13.1.3 无服务器

无服务器(Serverless):一种计算模型,开发者无需管理服务器,云平台自动管理资源分配和扩展。

  • 函数即服务(FaaS, Function as a Service)
    • 以函数为单位部署和执行代码
    • 按执行次数和时长计费
    • 典型产品:AWS Lambda、Azure Functions、Google Cloud Functions
    • 适合事件驱动、微服务、API后端等场景
  • 事件驱动(Event-Driven)
    • 函数由事件触发执行(HTTP请求、消息队列、定时任务等)
    • 自动扩展,无需预配置容量
    • 按需执行,空闲时无成本
  • 冷启动(Cold Start)
    • 函数首次调用或长时间未调用后的启动延迟
    • 包括:容器启动、运行时初始化、代码加载
    • 可能影响延迟敏感的应用
    • 优化方法:预热、使用预留并发、减少依赖

13.2 性能优化

13.2.1 应用优化

  • 代码优化
  • 依赖优化
  • 缓存策略
  • 异步处理

13.2.2 基础设施优化

  • 选择合适的服务
  • 优化网络配置
  • 使用缓存服务
  • 数据库优化

第五部分 性能优化

第14章 系统和应用程序性能优化

14.1 优化方法论

14.1.1 优化流程

  1. 问题识别:识别性能瓶颈
  2. 量化分析:测量和量化问题
  3. 优化方案:制定优化策略
  4. 实施优化:执行优化措施
  5. 验证效果:验证优化效果
  6. 持续监控:持续监控性能

14.1.2 优化原则

  • 先测量,后优化:基于数据优化
  • 优化热点:优先优化影响大的部分
  • 权衡考虑:考虑成本、复杂度
  • 避免过度优化:保持代码可维护性

14.2 系统级优化

14.2.1 操作系统优化

  • 内核参数调优
  • 文件系统优化
  • 网络参数优化
  • 进程调度优化

14.2.2 硬件优化

  • CPU选择:核心数、频率
  • 内存配置:容量、速度
  • 存储选择:SSD、NVMe
  • 网络配置:高速网卡

14.3 应用级优化

14.3.1 代码优化

  • 算法优化
  • 数据结构优化
  • 减少对象创建
  • 避免不必要的计算

14.3.2 架构优化

  • 缓存策略
  • 异步处理
  • 负载均衡
  • 数据库优化

14.4 优化案例

(待补充具体优化案例)


第15章 云环境中的性能优化

15.1 云环境特性

15.1.1 弹性扩展

  • 自动扩展:根据负载自动调整
  • 预测扩展:基于历史数据预测
  • 成本优化:平衡性能和成本

15.1.2 多区域部署

  • 地理分布:多区域部署
  • 延迟优化:就近访问
  • 容灾备份:高可用性

15.2 云优化策略

15.2.1 实例优化

  • 选择合适的实例类型
  • 使用预留实例
  • Spot实例使用
  • 实例大小调整

15.2.2 网络优化

  • 使用CDN
  • 多区域部署
  • 私有网络
  • 网络加速

15.2.3 存储优化

  • 选择合适的存储类型
  • 使用缓存
  • 数据压缩
  • 存储分层

15.3 成本优化

15.3.1 资源优化

  • 资源利用率优化
  • 闲置资源清理
  • 预留实例使用
  • Spot实例使用

15.3.2 架构优化

  • 无服务器架构
  • 容器化部署
  • 微服务架构
  • 事件驱动架构

总结

《性能之巅》提供了系统性能分析的全面方法论,从基础概念到具体实践,涵盖了:

  1. 性能分析方法:USE方法、工作负载分析、延时分析等
  2. 系统性能:CPU、内存、存储、网络性能分析
  3. 应用性能:JVM、数据库、Web应用性能优化
  4. 云性能:云计算环境下的性能挑战和优化

关键要点:

  • 性能分析需要系统性的方法
  • 测量是优化的基础
  • 延时是量化性能的重要指标
  • 不同层级需要不同的优化策略
  • 云环境带来新的性能挑战和机遇

通过系统性的性能分析和优化,可以显著提升系统性能,改善用户体验。