戴夫,你不能只是测量程序的性能。你必须运行基准测试!
每当我询问某些程序的性能时,我都会听到这样的话。嗯,这只是有点正确。如果你想知道程序在什么负载下会成为瓶颈,你需要多大的机器来处理 100 个请求,或者你多久需要升级服务器,那么你可以测量它。你只需要用一种不同于你期望的方式来做。
如果一个程序每秒必须完成特定数量的工作,你通常会查看它在给定负载下使用的 CPU 量,并尝试进行乘法运算。如果你在每秒 5 个请求时使用 40% 的 CPU,并且想要将负载增加三倍,你可以可靠地说“15 个请求将占用 120% 的 CPU。这行不通。”
但是,如果你想每秒运行 10 个请求,那将占用 80% 的 CPU,你就不会那么有信心了。当然,你会想做一个基准测试并绘制出性能曲线。
那是因为你使用了错误的图表。
还记得在教科书中看到的两个图表(图 1 和图 2)吗?图 1 中显示的图表通常标记为利用率或吞吐量,上升到某个值,然后趋于平稳。
这很可能就是你习惯的,而且单位也是你想要使用的,所以这可能是你尝试使用的图表。你可以看到 150% 将完全超出曲线范围,所以这行不通,而 50% 在曲线的线性部分,所以这行得通。
图 2 中的图表没有引起太多关注,因为它使用的单位不常用,而且似乎没有提供任何东西,即使你可以看出它们在某种程度上是相互关联的。
图 2 中的图表是响应时间曲线,通常称为“曲棍球棒曲线”,或简称为“_/”。唯一始终使用它的人是容量规划师和性能工程师。他们使用它是因为他们可以进行一些测量,绘制一些线条,并可靠地估计两条曲线。
他们从时间开始,而不是百分比。他们测量程序完成一个操作需要多长时间,缓存全部预热,没有其他程序运行,使用一堆样本值,每个样本值都只发生一个操作。
假设你要请求一个图像,当你测量时,对你的程序的单个请求需要 100 毫秒——十分之一秒。这是服务时间,它是响应时间的主要组成部分:图 2 中向上和向右延伸的曲线。它向上转折的点称为拐点,也是第一个图表中利用率或吞吐量曲线开始趋于平稳的点。
此时,你可能已经注意到一件事:这就是你希望保持在 80% 的东西,以获得最佳性能。
容量规划师或性能工程师可以使用电子表格中的线条估算第二个图表,使用排队网络程序绘制曲线,或者使用模型构建器进行正式实验,该模型构建器对应用程序进行检测,然后从中构建一个或多个排队网络。这就是你需要知道的信息
1. 程序在什么负载下会成为瓶颈?
2. 处理 100 个请求需要多大的机器?
3. 服务器多久需要升级?
假设你有一个电子表格和一个数据点——每秒 1 个请求时为 100 毫秒——并且你想要以每秒请求数来工作。你想回答之前的三个问题。
以前,使用排队网络对此类问题进行建模表明,你正在两条直线之间绘制双曲线,并且两条直线的方程几乎完全由以下因素决定
• 你测量的一个数据点。
• 你希望绘制的其他数据点的仔细选择方式。
让我们从绘制线条开始,看看它本身能揭示多少信息。
第一条线很容易:它是双曲线“下肢”将要开始接近的水平线。它从 100 毫秒开始,并且由于它是水平的,因此对于你想要使用的所有 X 值都保持在那里。这是图 2 中的黄色水平线。
第二条线具有从 100 毫秒和 X 为零的点计算出的斜率。后者在负值 (1 秒 − 100 毫秒) = -0.9 秒
处。这两个相关的数据点决定了图表中的倾斜黄色线:它从 -0.9
开始,并以 y = 0.1x − 0.9
的斜率向上倾斜。它几乎正好在每秒 10 个请求处与水平线交叉,这是拐点——不仅在下曲线中,而且在上曲线中也是如此。
现在你可以回答一些关于性能的问题了。
1. 何时会成为瓶颈?每秒 8 到 10 个请求之间。拐点在 10,并且它将在每秒 8 个请求左右开始大幅减速。
2. 100 个请求需要多大的机器?你刚刚计算出一个单 CPU 的安全非瓶颈值,即 8 个请求,因此你需要 100/8 = 12.5 个 CPU
。
3. 机器何时必须升级?这取决于你的业务增长速度。
假设机器上的负载与业务增长速度完全相同。在这种情况下,你可以与高级管理层坐下来,获得一个增长数字用于容量规划。它可能是一个百分比/年,因此你必须计算出一个复合增长图,然后看看在你达到每秒 8 个请求之前需要多长时间。
此时,你可以停止:你知道程序何时会成为瓶颈,你可以根据此估算和预算。
但是为什么这有效?你如何获得像图 2 中那样漂亮的曲线?你如何将此应用于大型事物,例如机器或集群的容量规划?
这些问题的答案都涉及排队网络,因此让我们看看真正发生了什么。提示:它涉及队列的建立。
让我们从绘制一条水平线开始,表示一秒,以及一些方块,每个方块表示正在处理的一个请求。
请求 1 需要 100 毫秒(十分之一秒)。请求 2 也是如此。但是,请求 3 有一个问题。请求 2 仍在运行。请求 3 在一秒内的 310 毫秒到达,但无法运行 90 毫秒。那是灰色区域,在绿色服务时间之前。请求 3 需要 190 毫秒——100 毫秒运行和 90 毫秒等待。不好!
请求 3 的总响应时间为 190 毫秒,因为它必须排队等待。请求 4 也有同样的问题,请求 5 甚至更糟。
这解释了延迟:如果你有比当前可以处理的更多的工作进来,那么有些东西必须排队等待轮到它运行。
曲线来自概率。
在每秒 1 个请求时,两个请求同时出现的可能性为零。在每秒 10 个请求时,很可能一堆请求几乎同时出现,落后者将不得不排队等待。
如果你平均足够大的样本,你将看到一条曲线,该曲线开始时几乎平行于 x 轴,并弯曲向上以平行于对角线。
有排队网络求解器可以绘制曲线:最好的求解器之一是尼尔·冈瑟的 PDQ,1 我用它来绘制表 1 以及图 1 和图 2。如果你对容量规划背后的科学感兴趣,冈瑟的书籍是必备品。
请注意,我尚未解释电子表格中倾斜线的方程。那是因为我想先绘制绿色方块的对角线。
只看图 3 中的绿色方块,你会注意到它们形成了一条向上和向右的对角线。这代表了机器可以做的最好的事情。如果负载不大,则可能存在间隙,例如在请求 1 和请求 2 之间,但如果请求一个接一个地进来,它们会形成一条从角到角的方块线。
实际上,它与图 2 中的对角线相同。在图 4 中,它在电子表格中绘制,使用公式 y = 0.1x − 0.9
(黑底白字),其中
• 0.1 是曲线的斜率,等于以秒为单位的服务时间。它使线条以 45 度角向上和向右倾斜。
• 0.9 是一秒减去服务时间。它使倾斜线在略低于每秒 10 个请求时高于零。我选择以每秒请求数为单位进行计算以简化计算,因此 0.9 秒是每秒 1 个请求时请求之间的时间量。它有时被称为“睡眠”时间 Z
。
因为你不能同时做两件事(至少每个核心),所以机器会成为瓶颈,作业最终会排队,你可以在电子表格上画一条线,表示当你给机器太多工作要做时导致的延迟。
假设你被要求为图书销售网站提供封面插图,对于标准尺寸的图像,这需要 100 毫秒。但是,在这种情况下,你需要完成时间少于 150 毫秒。如果速度太慢,书将不会显示,最终客户将不会购买它,并且你将因承诺你无法做到的事情而陷入困境。
为了在平均 150 毫秒内响应,你必须将限制设置为小于每秒 12 个请求。但是少多少呢?接受太多并对所有请求都太慢会浪费你所有的努力。
这就是排队网络的优势所在:解决低负载到 80% 或 90% 负载时的响应时间。使用 PDQ,你将获得如表 1 所示的结果:向下查看响应列,查看何时达到 0.15 秒,它处于比预期小得多的负载下。如果要保持在每请求 0.15 秒以下,则可以接受每秒 5 个请求。
你的客户报告显示,在一天中的高峰时段大约有每秒 80 个请求,并且你有一台 20 核机器专用于此任务。如果每个 CPU 每秒最多可以处理 5 个请求,则该机器将每秒处理 100 个请求。
你确信你可以实现每秒 80 个请求,因此即使在这些严格的条件下,也值得尝试。
嗯,不是。我与其说是构建电子表格和 PDQ 模型,不如说是使用它们。
对于大型作业,我使用 Teamquest Predictor,2 它是一个软件包,已经知道如何收集有关服务器中队列可能建立的多个位置的数据。这是询问“我多久需要升级服务器?”的经典工具。
使用建模器,我可以从尚未发生故障的机器收集数据,并预测如果负载每季度增加一定百分比会发生什么情况。当我发现瓶颈时,我可以告诉模型假装我已经添加了 CPU、内存或磁盘,并查看我需要多少来修复瓶颈。
图 5 说明了模拟的 CPU 队列延迟累积并开始使小型文件服务器成为瓶颈,直到第二年晚些时候向模拟添加第二个 CPU,它才恢复。然后,I/O 队列在第三年开始增长,直到添加了更多的磁盘头,与已添加的 CPU 成比例。
使用这样的模型,你可以尝试向机器添加计划的未来负载,并提前了解何时必须为额外的 CPU 和磁盘或内存编制预算。
每当你遇到性能或容量规划问题时,都不需要进行全面的基准测试。一个简单的测量将提供系统的瓶颈点:示例程序在每个 CPU 每秒超过 8 个请求后会显着变慢。
这通常足以告诉你最重要的事情:你是否会失败。
它不会告诉你你一定会成功,但是知道你是否注定要失败在你被要求开始一个项目时真的非常重要。而且你不必运行基准测试来找出答案。
1. Gunther, N. J. 2005. Analyzing Computer System Performance with Perl::PDQ. New York: Springer; http://www.perfdynamics.com. (我特别推荐 Gunther 的Guerrilla Capacity Planning)。
2. Teamquest Predictor,前身为 Teamquest Model; https://www.fortra.com/blog/teamquest-acquisition-two-and-half-years-later。
大卫·科利尔-布朗是一位作家和系统程序员,曾任职于 Sun Microsystems,主要在他的多伦多基地从事性能和容量工作。
版权所有 © 2023,所有者/作者持有。出版权已授权给 。
最初发表于 Queue vol. 21, no. 2—
在 数字图书馆 中评论本文
Peter Ward, Paul Wankadia, Kavita Guliani - 在 Google 重新发明后端子集化
后端子集化对于降低成本非常有用,甚至对于在系统限制内运行可能是必要的。十多年来,Google 一直使用确定性子集化作为其默认后端子集化算法,但尽管此算法平衡了每个后端任务的连接数,但确定性子集化具有较高的连接流失率。我们在 Google 的目标是设计一种具有降低的连接流失率的算法,该算法可以替代确定性子集化作为默认后端子集化算法。
Noor Mubeen - 工作负载频率缩放定律 - 推导与验证
本文介绍了与每个 DVFS 子系统级别的工作负载利用率缩放相关的方程式。建立了频率、利用率和缩放因子(其本身随频率变化)之间的关系。这些方程式的验证被证明是棘手的,因为工作负载固有的利用率也看似以未指定的方式在治理样本的粒度上变化。因此,应用了一种称为直方图脊迹的新方法。在将 DVFS 视为构建块时,量化缩放影响至关重要。典型应用包括 DVFS 调控器和/或其他影响系统利用率、功耗和性能的层。
Theo Schlossnagle - DevOps 世界中的监控
监控可能看起来非常繁琐。最重要的是要记住,完美永远不应成为更好的敌人。DevOps 使组织内部能够进行高度迭代的改进。如果你没有监控,那就获取一些;获取任何东西。有总比没有好,如果你已经接受了 DevOps,那么你已经同意随着时间的推移使其变得更好。
Ulan Degenbaev, Jochen Eisinger, Manfred Ernst, Ross McIlroy, Hannes Payer - 空闲时间垃圾回收调度
Google 的 Chrome 浏览器致力于提供流畅的用户体验。动画将以 60 FPS(每秒帧数)更新屏幕,这给 Chrome 大约 16.6 毫秒的时间来执行更新。在这 16.6 毫秒内,必须处理所有输入事件,必须执行所有动画,最后必须渲染帧。错过截止日期将导致丢帧。这些对用户可见并降低用户体验。此类零星的动画伪影在此处被称为卡顿。本文介绍了一种在 Chrome 使用的 JavaScript 引擎 V8 中实现的方法,用于在 Chrome 空闲时安排垃圾回收暂停。