本月,我与芝加哥的一家公司合作,以提高AIX上电子商务套件的性能。多年来,我已经多次使用AIX上运行的数据库。尽管如此,这周我还是陷入了困境。
TLDR:归根结底,这是IBM在2010年推出POWER7处理器时对资源计费的一个根本性改变。底线有两个:
如果启用了SMT,那么CPU利用率数字的含义就会改变。单个进程的CPU利用率数字意味着一些全新的东西。
oracle database 11.2.0.3(我没有测试新版本,但它们可能也会受到影响)没有意识到这一变化。因此,如果在AIX/POWER7/SMT上运行,AWR报告和扩展SQL跟踪中捕获的所有CPU时间值都是错误的和误导性的。(我没有在数据库的其他地方测试CPU时间值,但它们也可能是错误的。)
在其他unix操作系统(例如带有英特尔超线程的Linux)上,单个进程的CPU数反映了该进程在CPU上花费的时间。这很简单:100%意味着进程在逻辑CPU上花费了100%的时间(也称为线程——超线程内核上的每个硬件线程上下文在Linux中都显示为CPU)。然而,使用SMT的AIX则不同。在AIX上,当您查看单个进程时,CPU利用率数字反映了IBM对物理容量使用百分比的看法。
IBM为什么这么做?我认为他们的总体目标是帮助我们进行全系统的监控和能力规划——但这是以调整单个流程为代价的。他们试图解决SMT固有的真正缺点——但作为一个做了大量性能优化的人,我发现他们的改变让我的生活更加困难!
Ls Cheng于2012年11月在Oracle-L邮件列表上开始了一次对话,讨论了他在启用了SMT的AIX上的数据库,AWR报告中的CPU数甚至没有正确相加。乔纳森·刘易斯(Jonathan Lewis)认为重复计算是最简单的解释,而卡尔·阿拉奥(Karl Arao)则提出了CPU运行队列中的时间的理由。最终的解决方案从未公布在清单上——但事后看来,这几乎肯定与我在本文中研究的问题相同。它愚弄了我们所有人。AIX/Power7/SMT上的CPU密集型工作负载经常会误导性能专家,让他们认为操作系统级别存在CPU运行队列问题。事实上,在为本文做了研究之后,我回去查看了我自己在2011年8月与AIX/SMT客户进行咨询时的最终报告,并意识到我自己犯了这个错误!
据我所知,Marcin Przepiorowski是第一个真正“破解”这个案子的人,他在2013年2月研究并发表了一篇详细的解释,文章是《AIX上的Oracle——我的cpu时间在哪里?》?。史蒂夫·皮特曼(Steve Pittman)在2012年12月的一篇文章《理解电力系统(AIX)上的处理器利用率》(Understanding Processor Utilization on Power Systems)中发表了详细的解释,马辛从中得到了消息。Karl Arao也在2013年对其进行了研究,并在其复杂的cpu aix工具tiddlywiki页面上发布了大量信息。最后,格雷厄姆·伍德(Graham Wood)同时也在深入研究,并为橡木桌成员之间的几次对话做出了贡献。我只是想明确一点,我没有发布任何新的发现!:)
然而——尽管它已经公开了几年——大多数人都不知道这有多重要,甚至不知道技术上的问题到底是什么。这就是我认为我可以做出贡献的地方:通过对史蒂夫、马辛和卡尔记录的行为进行一些简单的演示。
我最近花了几年时间为一家云/SaaS公司领导数据库操作。也许这份工作最引人注目的一个方面就是我从“年轻人”变成了“老家伙”!我当然不是公司里年龄最大的人,但有一半以上的同事比我年轻!
嗯,我这一代人可能是最后一个记得拥有没有多任务的个人电脑的人。好吧……我知道我仍然和很多学会用穿孔卡片编程的人一起工作。但另一方面,当我的许多年轻同事开始使用技术时,我认为DOS已经过时了!你们中的一些年轻开发人员是从Windows 95开始的。你的电脑总是可以在不同的窗口同时运行两个程序。
有时你会对自己亲身经历和欣赏的科技进步多加注意。我记得当我们家有了第一台一次可以做不止一件事的电脑时,这是一件大事!多任务(或分时)不是一个复杂的概念。但这很重要,也是基础性的。
所以很明显(我希望),如果有多个进程,只有一个CPU,那么这些进程将轮流运行。关于操作系统是否、何时以及如何强制某个进程脱离CPU,存在一些细微差别,但最重要的是要理解上面所示的时间线。因为在这篇博文的其余部分,我们将讨论性能和时间。
下面是一个具体的例子:我的笔记本电脑CPU的一个核心可以在大约4-5秒内通过内存复制13GB的数据:
$time-p任务集2 dd if=/dev/zero of=/dev/null bs=64k count=200k
linux上的“taskset”命令将命令固定在特定的CPU#2上,因此“dd”只能在该CPU上执行。这样,我的示例运行起来与上图完全相同,只有一个CPU。
$time-p任务集2 dd if=/dev/zero of=/dev/null bs=64k count=200k&;
当然,这需要两倍的时间——9-10秒。我在linux笔记本电脑上运行了这些命令,但在任何平台上都可以观察到相同的结果。顺便说一句,请注意“sys”数字仍然是4-5秒。这意味着每个进程实际上在CPU上执行了4-5秒,尽管它需要9-10秒的挂钟时间。
上面的“time”命令提供了实际(挂钟)时间的摘要,以及进程在用户和系统模式下在CPU上执行的时间。这段时间由操作系统内核进行跟踪和说明。linux“time”命令使用wait4()系统调用来检索CPU记帐信息。这可以通过strace进行验证:
$strace-t time-p dd if=/dev/zero of=/dev/null bs=64k count=200k
关于这一点,有两个注释。首先,您将从时间戳中看到,在wait4()系统调用期间有5秒的暂停,“dd”的输出会中断其输出。显然,这是“dd”运行的时候。其次,您将看到wait4()调用返回两个变量,分别为ru_utime和ru_stime。wait4()上的手册页阐明了该返回参数是POSIX规范中定义的rusage结构。该结构是及时定义的。h和是getrusage()和times()返回的相同结构。这就是操作系统内核如何将计时信息返回到“time”以便在输出上显示的方式。
由于许多人都熟悉Linux,因此提供Linux/Intel/Hyper-Threading与AIX/Power7/SMT的并行比较将很有帮助。这也将有助于明确AIX到底在做什么,这很不寻常。
为了进行比较,我们将切换到Amos Waterland的有用的压力实用程序来生成CPU负载。该程序可用于所有主要的unix版本,并通过旋转sqrt()函数干净地加载CPU。我在佩兹找到了一份。org已经为POWER上的AIX进行了移植和打包。
为了进行比较,我们将加载一个空闲CPU 100秒的挂钟时间。我们知道进程将在CPU上旋转100秒,但让我们看看操作系统内核如何报告它。
user@debian:~$lscpu |白鹭#39;(姓名)和#39;
接下来,让我们运行我们的压力测试(固定在单个CPU上),并查看内核报告的CPU使用情况:
user@debian:~$time-p任务集2压力-c1-t100
正如我们所料,系统处于空闲状态,进程在CPU上持续了100秒。
现在,让我们使用mpstat在第二个窗口中查看CPU#2的利用率:
user@debian:~$mpstat-P1010 12页
同样,这里没有什么意外。我们看到,在压力测试期间,CPU以100%的速度运行。
接下来,让我们检查系统范围的视图。在linux上,大多数人使用top命令来查看系统范围内发生了什么。顶部显示进程列表,并估计每个进程在CPU上花费的时间。请注意,“top”实用程序使用的是/proc/<;PID>/stat文件来获取内核跟踪的CPU时间,而不是libc调用——但这仍然会返回与“time”命令相同的数据。然后除以墙上的时钟时间,以百分比的形式表示CPU时间。如果两个进程在一个CPU上运行,那么每个进程将报告50%的CPU利用率(在默认的Irix模式下)。
我们将在第三个窗口中运行top,同时运行stress和mpstat程序以获得系统范围的视图:
LinuxTop(在Irix模式下)报告说,“压力”程序使用了100%的单个CPU,系统使用了我总CPU容量的26.3%。
这是错误的。你发现我上述陈述的问题了吗?如果你有任何支持超线程的linux服务器,那么我真的希望你能理解这一点!
问题在于第二种说法——我总CPU容量的26%被使用了。实际上,“硬件线程”与“真正的核心”完全不同。(对于Oracle有关超线程和CPU容量的详细信息,Karl Arao可能是最好的信息来源之一。)Linux内核开发人员将每个硬件线程表示为一个逻辑CPU。因此(这是违反直觉的)将“总CPU利用率”视为与总CPU容量相关的数字是非常误导的。
这对你意味着什么?必须将Linux/超线程上的CPU监控阈值设置得非常低。您可以将分页的临界阈值设置为70%。就个人而言,我喜欢将事务系统的利用率保持在50%以下。如果你的超线程linux系统有70%的CPU利用率,那么你很快就会耗尽CPU!
为什么这很重要?这正是IBM的AIX团队使用SMT on POWER解决的问题。但有一个问题:标准工具用于计算系统级CPU使用率的源数据是POSIX定义的“rusage”进程会计信息。IBM调整了rusage的含义,以解决我们的系统级CPU报告问题,并在单个进程级别引入了一个新问题。我们来看看。
#prtconf | grep处理器
所以你可以看到,我们在SMT4模式下使用2到4个POWER7处理器,这将显示为8到16个逻辑处理器。
#ps-o螺纹
等等…我的CPU时间到哪里去了?!(这也是马辛最先注意到的事情之一!)AIX内核报告我的进程运行了100秒的挂钟时间,但它只在CPU上运行了65秒!
在unix版本(如Linux)上,这意味着操作系统没有在丢失的时间内尝试将进程放在CPU上。可能进程正在等待磁盘操作或来自另一进程的信号。但是我们的压力测试只执行sqrt()函数,所以我们知道它没有等待任何东西。
当您知道进程没有等待时,操作系统不会将进程放在CPU上的唯一原因是。再看看本文中的第一个演示:共享CPU需要两个(或更多)进程。请注意,用户+系统时间低于挂钟时间,与我们在AIX上的输出完全相同!
因此,让我们在第二个窗口中使用“nmon”实用程序来查看系统范围的视图。(topas报告的是solaris风格的CPU使用情况,而nmon报告的是irix风格的CPU使用情况,因此nmon更适合此测试。它们实际上是相同的二进制文件,只是调用方式不同而已。)
等等…这好像不对!我们的“压力”进程是系统上运行的唯一进程,我们知道它只是通过sqrt()调用来旋转CPU。“nmon”工具似乎验证了time命令的输出——进程只有65%的时间在CPU上!为什么AIX不让我的进程在CPU上运行?!
让我们看看mpstat命令的输出,我们在第三个窗口中运行该命令:
#mpstat 10 12 |白鹭和#39;(cpu |^4)和#39;
处理器4正在100%运行。您应该马上意识到,我们解释nmon输出的方式有问题,因为我们的“压力”进程是这个处理器上唯一运行的东西。mpstat实用程序没有使用内核的rusage进程记帐数据,它表明我们的进程是在CPU上全职运行的。
那么,IBM到底做了什么?答案——史蒂夫和马辛几年前发表的——从名为“pc”的mpstat小专栏开始。这代表“物质消费”。(在sar-P输出和topas/nmon中称为“physc”。)这就引出了IBM解决全系统CPU报告问题的核心。
IBM从容量而不是时间的角度来考虑一切。pc号是一个分数,它可以缩小利用率,以反映核心(物理cpu)而不是硬件线程(逻辑cpu)的利用率。在SMT-4芯片上,它们不只是除以4。功率处理器硬件实时动态计算分数,并通过名为PURR的新寄存器公开分数。IBM做了很多测试,然后——从POWER7开始——他们将智能内置到POWER处理器硬件中。
在我们的示例中,我们在SMT-4模式下100%使用一个SMT硬件线程。POWER处理器通过PURR寄存器报告,这代表处理器容量的65%,通过mpstat中的pc缩小系数0.65暴露给我们。我的POWER7处理器声称,如果一个处理器的四个线程以100%的速度运行,那么它只有65%的忙。
我还以SMT-4模式在同一个处理器上以100%的速度使用两个SMT硬件线程运行了测试。处理器将两个线程的规模缩小到45%,这样当你把它们加在一起时,处理器就声称它有90%的忙——尽管nmon&;topas将显示两个进程中的每一个仅以45%的CPU运行!当所有四个线程在SMT-4模式下以100%的速度使用时,处理器当然会将所有四个进程的规模缩小到25%——处理器最终会显示它是100%忙碌的。
在旁注中,%ec列显示了实际消耗量占授权容量(2个处理器)的百分比。我假设的65%的处理器利用率相当于我整个系统容量的32.6%。并非巧合,topas显示的“压力”过程以32.6%的速度运行(就像我说的,solaris风格)。
因此,当AIX填充POSIX rusage进程记帐结构时,它会考虑PURR比率。好处是什么?Topas和其他监控工具通过计算处理器和/或进程利用率来计算系统负载。通过不断改变意思
......