1 Introduction

性能是一个令人兴奋、多样且具有挑战性的领域。本章介绍了性能领域,特别是系统性能,描述了其中的角色、活动、视角和挑战。它还介绍了延迟,这是一个关键的性能指标,并介绍了计算领域的一些新发展:动态跟踪和云计算。还包括一些性能活动的示例,以提供背景信息。
1.1 Systems Performance
系统性能是对整个系统进行研究,包括所有物理组件和完整的软件栈。任何在数据路径中的软件或硬件都应被纳入考虑,因为它们会影响性能。对于分布式系统,这意味着多个服务器和应用程序。如果您没有显示数据路径的环境图表,请找到一个或自己画一个;它将帮助您理解组件之间的关系,并确保您不会忽略整个区域。
图1.1显示了单个服务器上通用系统软件栈,包括操作系统(OS)内核,以及示例数据库和应用程序层。术语“整个栈”有时用来描述仅包含应用程序环境的情况,包括数据库、应用程序和 Web 服务器。然而,在谈到系统性能时,我们使用“整个栈”来表示包括系统库和内核在内的所有内容。

这个栈在第3章《操作系统》中进行了讨论,并在后面的章节中进行了更详细的研究。以下几节将描述系统性能和性能的一般情况。
1.2 Roles
系统性能作为一项活动,可以由各种角色来完成,包括系统管理员、支持人员、应用程序开发人员、数据库管理员和 Web 管理员。对于其中许多人来说,性能是一项兼职活动,并且可能倾向于仅在自己负责的领域内探索性能问题(网络团队检查网络,数据库团队检查数据库等)。然而,对于一些性能问题,要找到根本原因需要这些团队的合作努力。
一些公司雇佣了性能工程师,他们的主要工作是系统性能。他们可以与多个团队合作,并对环境进行全面研究,这种方法在解决复杂性能问题时可能至关重要。他们还可以识别机会,为跨环境的系统级分析和容量规划开发更好的工具和指标。
在性能领域还有专门的应用程序职业,例如针对Java性能和MySQL性能的职业。这些通常会从对系统性能的有限检查开始,然后转向特定于应用程序的工具。
1.3 Activities
性能领域包括以下活动,按照理想的执行顺序列出:
1. 设定性能目标和性能建模
2. 原型软件或硬件的性能特性分析
3. 开发代码的性能分析,在集成之前
4. 对软件构建进行非回归测试,在发布前或发布后
5. 为软件发布进行基准测试
6. 在目标环境中进行概念验证测试
7. 针对生产部署进行配置优化
8. 监控正在运行的生产软件
9. 对性能问题进行性能分析。
步骤1到5是传统软件产品开发的一部分。然后产品被推出市场,随后进行在客户环境中的概念验证测试或部署和配置。如果在客户环境中遇到问题(步骤6到9),意味着在开发阶段未能检测或修复该问题。
性能工程理想情况下应在选择硬件或编写软件之前开始。这可以是第一步,涉及设定目标和创建性能模型。然而,通常产品在没有经过这一步的情况下进行开发,将性能工程工作推迟到出现问题时再进行。然而,随着开发过程的每个步骤,由于之前做出的架构决策,修复性能问题可能会越来越困难。
容量规划这个术语可以指前面提到的一系列活动。在设计阶段,它包括研究开发软件的资源占用情况,以评估设计是否能满足目标需求。在部署后,它包括监控资源使用情况,以预测问题的发生。
本书介绍了一些方法和工具,用于执行这些活动。
不同公司和产品之间的环境和活动各不相同,在许多情况下,并不会执行所有九个步骤。你的工作可能也只专注于其中一些或只有一个活动。
1.4 Perspectives
除了专注于不同的活动外,性能角色可以从不同的角度进行考虑。性能分析的两个视角在图1.2中标记为工作负载分析和资源分析,它们从不同的方向来接近软件堆栈。

资源分析的视角通常由系统管理员所采用,他们负责系统资源。而负责工作负载的交付性能的应用程序开发人员通常会专注于工作负载分析的视角。每个视角都有其自身的优势,在第2章“方法论”中进行了详细讨论。对于具有挑战性的问题,尝试从两个视角进行分析可能会有所帮助。
1.5 Performance Is Challenging
系统性能工程是一个具有挑战性的领域,原因包括它具有主观性,复杂性,并且通常涉及多个问题。
1.5.1 Performance Is Subjective    //主观
技术学科往往是客观的,以至于行业内的人们以黑白分明而著称。这对软件故障排除来说可能是正确的,因为错误要么存在,要么不存在,要么已经被修复,要么没有被修复。这些错误通常表现为容易被解释和理解的错误消息,表示存在错误。
另一方面,性能问题往往是主观的。在性能问题上,是否存在问题并不清楚,如果存在问题,何时已经被解决也不清楚。对于一个用户而言,可能被认为是“糟糕”的性能,因此是一个问题,但对于另一个用户来说,可能被认为是“良好”的性能。
考虑以下信息:
平均磁盘I/O响应时间为1毫秒。
这是“好”还是“坏”?虽然响应时间或延迟是可用的最佳指标之一,但解释延迟信息是困难的。在一定程度上,一个给定的度量是否“好”或“坏”,可能取决于应用程序开发人员和最终用户的性能期望。
通过定义明确的目标,例如设置目标平均响应时间,或要求某个百分比的请求在特定延迟范围内完成,可以使主观性变为客观性。在第2章“方法论”中介绍了其他处理这种主观性的方法,包括通过延迟分析将问题表达为其操作延迟的比率。
1.5.2 Systems Are Complex
除了主观性外,性能问题可能由于系统的复杂性和缺乏清晰的分析起点而成为一门具有挑战性的学科。有时我们从一个猜测开始,比如责备网络,而性能分析师必须弄清楚这是否是正确的方向。
性能问题也可能源于子系统之间的复杂相互作用,在单独分析时它们表现良好。这可能是由于级联故障,当一个组件发生故障时会导致其他组件的性能问题。要理解所产生的问题,您必须解开组件之间的关系,并理解它们的贡献方式。
瓶颈也可能是复杂的,并以意想不到的方式相关;修复一个瓶颈可能只会将瓶颈转移到系统中的其他地方,整体性能并没有如期望的那样得到改善。
除了系统的复杂性外,性能问题可能是由生产工作负载的复杂特性引起的。在这些情况下,它们可能永远无法在实验室环境中重现,或者只会间歇性地重现。
解决复杂的性能问题通常需要采用整体方法。整个系统——包括其内部和外部交互——可能都需要被调查。这需要一系列技能,通常一个人很难具备,这使得性能工程成为一项多样化且具有智力挑战的工作。
不同的方法可以指导我们应对这些复杂性,就像在第2章中介绍的那样;第6至10章包括了特定的方法论,针对系统资源如CPU、内存、文件系统、磁盘和网络进行了介绍。
1.5.3 There Can Be Multiple Performance Issues
通常情况下,找到一个性能问题并不是问题;在复杂的软件中通常存在很多问题。为了说明这一点,试着找到你操作系统或应用程序的错误数据库,然后搜索关键词"性能"。你可能会感到惊讶!通常情况下,即使在被认为具有高性能的成熟软件中,也会存在一些已知但尚未修复的性能问题。这在分析性能时又带来了另一个困难:真正的任务不是找到一个问题,而是辨别出最重要的问题或问题。
为了做到这一点,性能分析师必须量化问题的严重程度。有些性能问题可能与您的工作负载无关,或者只适用于很小的程度。理想情况下,您不仅要量化问题,还要估计每个问题修复后的加速效果。当管理层寻求为工程或运营资源开支提供合理性时,这些信息是有价值的。
当可用时,一个非常适合性能量化的指标是延迟。
1.6 Latency
延迟是等待所花费的时间的度量。广泛地使用时,它可以表示任何操作完成所需的时间,例如应用程序请求、数据库查询、文件系统操作等。例如,延迟可以表示一个网站从链接点击到完全加载所花费的时间。这对于客户和网站提供者都是重要的指标:高延迟可能导致沮丧,客户可能会选择其他地方进行业务。

作为一个指标,延迟可以用来估计最大的加速效果。例如,图1.3描述了一个数据库查询需要100毫秒(即延迟),其中有80毫秒被阻塞等待磁盘读取。通过消除磁盘读取(例如通过缓存),可以计算出最大的性能提升:最多可以提升五倍(5倍)。这就是估计的加速效果,该计算还量化了性能问题:磁盘读取导致查询运行速度最多慢了5倍。
使用其他指标进行这样的计算是不可能的。例如,每秒I/O操作次数(IOPS)取决于I/O的类型,并且通常不能直接进行比较。如果某个更改将IOPS速率降低80%,很难知道性能影响会是什么样。可能会减少5倍的IOPS,但如果每个I/O的大小(字节)增加了10倍呢?
在网络的上下文中,延迟可以指连接建立的时间,而不是数据传输时间。在本书中,术语在每章的开始处进行了澄清,以便清楚地了解这种上下文差异。
尽管延迟是一个有用的指标,但并不总是能够在需要的时间和地点获得。一些系统领域只提供平均延迟;有些甚至不提供任何延迟指标。随着动态跟踪技术的出现,可以从任意感兴趣的点测量延迟,并提供显示完整延迟分布的数据。
1.7 Dynamic Tracing
动态跟踪允许所有软件在生产中都可以被检测和测量。它是一种技术,可以在内存中获取CPU指令,并动态地构建仪器。这使得可以从任何正在运行的软件中创建自定义性能统计数据,提供远远超出内置统计数据的可观察性。以前由于缺乏可观察性而无法解决的问题现在可以解决。以前可能可以解决但难度极大的问题现在通常更容易解决。
动态跟踪与传统观察方法有很大不同,因此一开始很难理解其作用。考虑操作系统内核:分析内核内部就像进入一个黑暗的房间,系统统计数据就像放在内核工程师认为需要的地方的蜡烛。动态跟踪就像一个手电筒,你可以把它指向任何地方。
该技术首次以可用于生产的工具形式问世,这个工具就是DTrace,它提供了许多其他功能,包括其自己的编程语言D。DTrace是由Sun Microsystems开发的,并于2005年发布用于Solaris 10操作系统。它也是Solaris中首个作为开源提供的组件,后来被移植到了Mac OS X和FreeBSD,并目前正在被移植到Linux。
在DTrace之前,系统跟踪通常使用静态探测器进行,即在内核和其他软件中放置一小组仪器点。它们的可见性有限,使用它们经常很耗时,需要配置、跟踪、转储数据,然后进行分析的一个周期。
DTrace提供用户级和内核级软件的静态和动态跟踪,并可以实时提供数据。以下是一个简单的示例,跟踪ssh登录期间的进程执行情况。跟踪是系统范围的(不与特定进程ID相关):

在这个示例中,DTrace被指示打印时间戳(纳秒),并显示进程名称和参数。在D语言中可以编写更复杂的脚本,允许我们创建和计算自定义的延迟度量。DTrace和动态跟踪将在第4章《可观察性工具》中进行解释。在后面的章节中,有许多基于Linux和Solaris系统的DTrace单行命令和脚本示例。对于更高级的用法,还有一本单独介绍DTrace的书籍[Gregg 11]。
1.8 Cloud Computing
最近对系统性能产生影响的最新发展是云计算和云常用的虚拟化技术。云计算通过使用一种可以在越来越多的小型系统之间平衡应用程序的架构,实现了快速扩展能力。这种方法还减少了对严格容量规划的需求,因为可以随时从云端添加更多容量。在某些情况下,它还增加了对性能分析的需求:使用更少的资源可以意味着使用更少的系统。由于云使用通常按小时计费,所以通过减少系统数量来提高性能可以立即节省成本。将这种情况与企业客户进行比较,企业客户可能被锁定在数年的固定支持合同中,可能无法在合同结束之前实现成本节约。
云计算和虚拟化带来的新问题包括管理其他租户引起的性能影响(有时称为性能隔离)以及每个租户对物理系统的可观察性。例如,除非系统得到正确管理,否则由于与邻居竞争,磁盘I/O性能可能较差。在某些环境中,每个租户可能无法观测到物理磁盘的真实使用情况,这使得难以识别此问题。
这些主题在第11章《云计算》中进行了详细讨论。
1.9 Case Studies
如果您是系统性能方面的新手,可以通过展示何时以及为什么进行各种活动的案例研究来帮助您将它们与当前环境联系起来。这里总结了两个假想的例子:一个是涉及磁盘I/O的性能问题,另一个是针对软件更改的性能测试。
这些案例研究描述了在本书的其他章节中解释的活动。这里描述的方法旨在展示的不是正确的方法或唯一的方法,而是这些性能活动可以进行的一种方法,供您进行关键考虑。
1.9.1 Slow Disks
Scott是一家中型公司的系统管理员。数据库团队提交了一个支持工单,抱怨他们的一个数据库服务器上的“磁盘速度慢”。Scott的第一个任务是了解更多关于这个问题的情况,收集详细信息来形成一个问题陈述。工单声称磁盘速度慢,但没有解释这是否导致了数据库问题。Scott通过提出以下问题做出回应:
- 目前是否存在数据库性能问题?如何进行衡量?
- 这个问题存在多长时间了?
- 最近数据库有什么变化吗?
- 为什么怀疑是磁盘的问题?
数据库团队回复说:“我们有一个查询时间超过1,000毫秒的日志。通常这种情况不会发生,但在过去一周中每小时都有几十个。AcmeMon显示磁盘在忙碌。”这证实了确实存在一个数据库问题,但也表明磁盘假设很可能是一个猜测。Scott想检查磁盘,但他也想快速检查其他资源,以防那个猜测是错误的。
AcmeMon是公司的基本服务器监控系统,提供基于操作系统工具(mpstat(1)、iostat(1)等)的历史性能图形。Scott登录AcmeMon亲自查看。
Scott从一种称为USE方法的方法开始,快速检查资源瓶颈。如数据库团队所报道的,磁盘的利用率很高,约为80%,而对于其他资源(CPU、网络)的利用率则要低得多。历史数据显示,磁盘利用率在过去一周中稳步增加,而CPU利用率则保持稳定。AcmeMon不提供磁盘饱和度或错误统计信息,因此为了完成USE方法,Scott必须登录到服务器并运行一些命令。
他从/proc中检查磁盘错误计数器,结果为零。他运行iostat命令,间隔为一秒,并随时间观察利用率和饱和度指标。AcmeMon报告显示80%的利用率,但使用了一分钟的间隔。以一秒的粒度,Scott可以看到磁盘利用率波动很大,经常达到100%,导致饱和度水平升高和增加的磁盘I/O延迟。
为了进一步确认这是否阻塞了数据库,而不是与数据库查询异步进行,他使用基于动态跟踪的脚本来捕获每当数据库被内核挂起时的时间戳和数据库堆栈跟踪。这显示数据库经常在文件系统读取期间、查询期间以及持续数毫秒的时间内发生阻塞。这对于Scott来说已经是足够的证据。接下来的问题是为什么会发生这种情况。磁盘性能统计数据似乎与高负载一致。Scott进行工作负载特性分析以进一步了解情况,使用iostat(1)来测量IOPS、吞吐量、平均磁盘I/O延迟以及读/写比。通过这些数据,他还计算了平均I/O大小并估计访问模式:随机还是顺序。如果需要更多细节,Scott可以使用磁盘I/O级别跟踪;然而,他满意地认为这已经指向了高磁盘负载的情况,而不是磁盘的问题。
Scott在工单中增加了更多细节,说明了他所检查的内容,并包括了研究磁盘所使用的命令的屏幕截图。到目前为止,他的总结是磁盘处于高负载状态,这增加了I/O延迟并减慢了查询速度。然而,从负载情况来看,磁盘似乎表现正常。他询问是否有一个简单的解释:数据库的负载是否增加了?
数据库团队回复说没有,而且查询速率(这并未由AcmeMon报告)一直很稳定。这似乎与之前的发现一致,即CPU利用率也一直稳定。
Scott考虑到什么原因会导致磁盘I/O负载增加,而CPU没有明显增加,并与同事进行了快速交流。其中一位同事提出文件系统碎片化的可能性,当文件系统接近100%容量时,这是预期的。但实际上只有30%。
Scott知道他可以进行深入分析以了解磁盘I/O的确切原因,但这可能需要很长时间。他首先尝试想出其他易于检查的简单解释,基于他对内核I/O堆栈的了解。他记得这种磁盘I/O主要是由文件系统缓存(页面缓存)未命中引起的。
Scott检查了文件系统缓存命中率,发现当前为91%。听起来很高(很好),但他没有历史数据可以进行比较。他登录到其他提供类似工作负载的数据库服务器,发现它们的缓存命中率超过97%。他还发现其他服务器的文件系统缓存大小要大得多。
将注意力转向文件系统缓存大小和服务器内存使用情况,他发现了一个被忽视的问题:一个开发项目有一个原型应用程序,即使没有生产负载,也在消耗越来越多的内存。这些内存来自可供文件系统缓存使用的内存,降低了命中率,从而增加了磁盘I/O并影响生产数据库服务器。
Scott联系应用程序开发团队,并要求他们关闭应用程序并将其移动到另一台服务器,引用数据库问题。在他们这样做后,Scott观察到AcmeMon中的磁盘利用率逐渐下降,因为文件系统缓存恢复到原始大小。慢查询数量降为零,他将工单标记为已解决。
1.9.2 Software Change
Pamela是一家小公司的性能和可伸缩性工程师,负责所有与性能相关的工作。应用程序开发人员开发了一个新的核心功能,并不确定其引入是否会影响性能。Pamela决定在将新的应用程序版本部署到生产环境之前进行非回归测试。(非回归测试是用于确认软件或硬件更改不会导致性能退化的活动,因此被称为非回归测试。)
Pamela获取了一台空闲服务器用于测试,并寻找一个客户端工作负载模拟器。应用团队以前写过一个,尽管它有各种限制和已知的bug。她决定尝试使用它,但希望确认它是否充分类似于当前的生产工作负载。
她配置服务器以匹配当前的部署配置,并从不同的系统运行客户端工作负载模拟器到目标系统。通过研究访问日志,可以对客户端工作负载进行特征化,公司已经有一个工具可以做到这一点,她使用了这个工具。她还在不同时间的生产服务器日志上运行了这个工具,比较了工作负载。看起来客户端模拟器应用了一个平均的生产工作负载,但没有考虑变化。她注意到了这一点,并继续她的分析。
Pamela在这个阶段知道几种可以采用的方法。她选择了最简单的方法:从客户端模拟器增加负载,直到达到一个限制(工作负载)。客户端模拟器可以配置为每秒执行一定数量的客户端请求,其默认值为1,000,她之前已经使用过。她决定从100开始增加负载,每次增加100,直到达到一个限制,每个级别测试一分钟。她编写了一个shell脚本来执行测试,并将结果收集到一个文件中,以便由其他工具进行绘图。
在负载运行时,她进行主动基准测试以确定限制因素是什么。服务器资源和服务器线程似乎大部分处于空闲状态。客户端模拟器显示完成的请求大约稳定在每秒700个左右。
她切换到新的软件版本并重复测试。结果也达到了700个请求,并趋于稳定。她还分析了服务器以寻找限制因素,但仍然没有发现任何问题。
她绘制了结果,显示完成请求率与负载之间的关系,以直观地确定可伸缩性特征。两者似乎都达到了一个突然的上限。
尽管看起来软件版本具有类似的性能特征,但Pamela对于未能确定导致可伸缩性上限的限制因素感到失望。她知道自己只检查了服务器资源,而限制因素可能是应用程序逻辑问题。它也可能存在于其他地方:网络或客户端模拟器。
Pamela想知道是否需要采取不同的方法,例如运行固定速率的操作,然后对资源使用情况(CPU、磁盘I/O、网络I/O)进行特征化(资源使用),以便可以从单个客户端请求的角度来表示。她以每秒700个请求的速率运行模拟器,测试当前和新的软件,并测量资源消耗情况。对于给定的负载,当前软件将32个CPU的平均利用率提高到20%。对于同样的负载,新软件将相同的CPU利用率提高到30%。看起来确实存在回归问题,即消耗更多的CPU资源。
为了了解700的限制,Pamela增加了负载,并调查数据路径中的所有组件,包括网络、客户端系统和客户端工作负载生成器。她还对服务器和客户端软件进行了深入分析。她记录了自己所检查的内容,包括截屏,以供参考。
为了调查客户端软件,她进行了线程状态分析,并发现它是单线程的。这一个线程花费100%的时间在CPU上执行。这使她确信这就是测试的限制因素。
作为一项实验,她在不同的客户端系统上并行启动客户端软件。通过这种方式,她让服务器在当前软件和新软件下都达到了100%的CPU利用率。当前版本达到了每秒3,500个请求,而新版本达到了每秒2,300个请求,与先前的资源消耗结果一致。
Pamela通知应用程序开发人员,新软件版本存在回归问题,并开始对其CPU使用情况进行分析以了解原因:哪些代码路径在起作用。她指出进行了平均生产工作负载测试,但未进行各种工作负载测试。她还提交了一个bug,指出客户端工作负载生成器是单线程的,可能成为瓶颈。
1.9.3 More Reading
第13章《案例研究》提供了一个更详细的案例研究,记录了我如何解决一个特定的云性能问题。下一章介绍了用于性能分析的方法论,并且接下来的章节涵盖了必要的背景知识和具体内容。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值