发现瓶颈 - 基准测试的方法
基准测试的方法
?
一般在这之后,我们再来详细的说明怎样设计和执行基准测试。在我们讨论怎样能更好的做基准测试之前,先来看看一些错误,它们能导致不可用或者不准确的结果。
?
使用真实数据的子集,如本来这个应用需要处理几百G的数据,而测试数据仅为1G。再如,你计划这个程序处理的数据增长非常之快,而测试数据还是当前的数据量。使用不正确的分布式数据。当真实的系统有一些所关注的“热点”却均匀分布数据。(随机生成的数据是不真实的分布)使用不真实的分布参数(unrealistically distributed parameters)。假装所有的用户资料都是可见的。对于多用户的应用,使用单用户的场景。在单独的服务器上测试分布式应用。不符合实际的用户行为。比如在网页的“等待时间”(think time)。真正的用户请求一个页面然后再去阅读;没有停顿的情况下,他们不能依次的点击链接。在循环中执行同一语句。真正的语句不是相同的。因此它们忽略了缓存。相同的语句在某些级别被缓存了。没有检查错误。如果基准测试结果没有意义。比如,一个缓慢的操作突然变快了,请检查错误。你做的基准测试可能会快速发现了MySQL的语法错误。基准测试之后查看错误日志,是个比较重要的准则。忽略了系统没有预热(warmed up)下的执行情况。比如在重新启动之后,你要知道在启动之后,服务器需要多久才能达到一定的能力。因此就要看“预热”阶段,系统执行的情况。如果你要研究正常的性能,你需要关心的是,基准测试在服务器重启之后,许多缓存被清空的情况下,在系统预热之前,这基准测试是不能反映出正常的结果的。使用默认的服务器设置。以后会详细讲到。为了得到有质量的结果,避免了这些错误,只不过刚刚上路而已。基准测试计划的第一步就是发现问题和目标。接下来 决定是使用标准的基准测试还是自己设计一个。
?
如果你使用标准的基准测试,要选择一个适合你的需要。一个例子,不用TCP去基准测试电子商务系统。TCP已经说了。它比较适合决策支持系统。这个系统需要查看大量的数据。因此,它并不适合在线交易系统。
?
设计自己的基准测试是个比较复杂和迭代的过程。开始的时候,要做一个产品数据集的复制。确定在随后进行的测试,数据可以恢复。
?
接下来,需要针对数据运行大量的语句。你可以在基本的基准测试中创建一个单元测试包。你可以多次运行它,但是可能并不适合你使用数据库的方式。比较好的做法是在一个典型的时间段中如高峰期或一整天,在产品系统中记录所有的语句。如果你记录的语句在一个小时间段中,你可能需要选择很多的时间段。这样才能覆盖系统所有的活动。如语句的周报或者不在高峰时期的批量任务。
?
可以在不同级别记录日志。一个例子,如果你需要全栈的基准测试,那么就需要web服务器的日志。你也要开启MySQL的日志功能。如果你重新查看一个语句的日志,要重新新建一个独立的线程来执行,而不是仅仅重复执行这个语句。在日志中,为每一个连接创建一个独立的线程也是非常重要的。而不是把各个线程执行的语句弄混。日志应该显示链接哪个连接运行每条语句。
?
即使你不创建自己的基准测试,你也要应该有自己的基准测试计划。你的基准测试将会运行很多次以及你需要有能力去重新准确的创建它。计划意味着未来。你可能不会是下次运行基准测试那个人,即使你是,你可能也不会准确记住你第一次是怎样运行的。你的计划应该包含测试数据,设置系统的步骤以及预热(刚启动服务器的时候,性能并没有完全发挥的时候)的计划。
?
设计一些记录参数和结果的方法,并且仔细的记录系统运行情况。你的记录方法可能像电子表格或者记事本或者如复杂点的数据库。(记住,你可能需要写一些脚本区分析一些结果。因此它比那些电子表格和文本文件更容易处理)。
?
你可能会创建一个基准测试的目录,对于每个结果建立子目录。之后,可能会放置结果,配置文件或者记录每次运行情况。如果你的基准测试测量的数据要多于你所感兴趣的。有一些不需要的数据要好于丢失重要的数据,以及将来你可能会发现这些额外的数据非常有用。在基准测试中要尽量记录更多的信息。如CPU德使用。硬盘的I/O.以及网络流量分析。使用SHOW GLOBAL STATUS去发现一些计数统计等等。
?
获取精确地结果最好的获取精确结果的方法就是,你设计的基准测试可以回答你想回答的问题。你选对了正确的基准测试了么?你正在捕获的数据能解答你需要知道的问题?用错误的标准进行基准测试了?你可能知道的是I/O边界基准测试,但是运行CPU边界的基准测试去预测程序的性能了么?
?
接下来,确定你的基准测试结果是可以重复验证的。在每次运行的开始,尽可能的确保系统是在相同的状态下。如果基准测试很重要,你应该在每次运行都去重启动系统。如果你需要基准测试预热的服务器,你应该也要确定你的预热时间是足够的长以及是可重复验证的。如果预热是由随机的语句所组成,这个基准测试结果就是不能重复验证的。
?
如果基准测试更改了数据或者数据模型,要在每次运行之前,进行数据重置。往一个上千数据的表的测试结果当然是和百万级别的表是不一样的。在硬盘上的数据碎片和分布也可能让你的结果是不可重复验证的。一个方法确认物理布局是差不多相近的,那么就快速格式化以及一个分区的文件拷贝。
?
要当心一些外部读取,程序剖析以及监控系统,详细的日志,周期性的任务,以及其他能使你结果偏离的因素。一个比较典型的因素就是周期性任务(con job),往往运行在基准测试之中,或者一个巡查读取周期(Patrol Read cycle)或者一个在RAID上进行一致性的检查。一定要确定一切资源都是为了基准测试。如果其它的一些影响了网络的能力,或者基准测试运行在与其他服务器共享的SAN上。你的结果可能不会准确。
?
在每次的基准测试中,尽可能的少更改参数。在这场景中,叫做“隔离变量”。如果你必须更该一些,那么可能要冒着丢掉某些东西的风险。参数可能还依赖于其他参数。因此有的时候,你不能单独的修改它们。有的时候你甚至不知道它们是相关的,这就更增加了复杂性。
?
一般情况下,都是迭代更改基准测试的参数。而不是在各个运行之间去更改。举个例子,使用一种如(divide-and-conquer)的技术(在各个运行之间,把差异分成两部分)对于服务器能得出一个有价值的信息。
?
我们看到了很多在移植之后的基准测试,如从Oracle移植到MySQL。这往往是令人讨厌的。因为MySQL与Oracle相比,有很多不同类型的语句运行的效果要好。如果你想知道从oracle移植到MySQL之后,这个应用的表现如何。你就需要修改数据模型和在MySQL下的语句了。(在许多案例中,如你要创建一个跨平台的应用,你可能想知道,同一语句在两个平台上的表现,但是这种案例很少见)
?
你也不能在MySQL默认配置的情况下获得有意义的数据。因为默认的配置都是面向的是极小的应用和消耗非常少的内存。
?
最终,如果你得到的是一个奇怪的结果,不要把它作为坏的数据而丢弃。调查和尽力找出哪出了问题。你可能会得到有价值的结果,一个严重的错误,或者是基准测试的设计缺陷。
?
运行基准测试和分析结果一旦你准备好了所有的前期准备,你可以运行基准测试并获取并分析数据。
自动运行基准测试是个非常好的主意。这么做会提高结果的质量和精确程度。因为这能避免忘掉某个步骤或者每次运行都会有一些突发事件。它也能帮助你记录基准运行的方式。
?
任意的自动化方法都可以做,如,Makefile或者一些脚本。你可以任意选择一些脚本语言:shell,php,Perl等等。尽可能的让更多的步骤进行自动化。包括了读取数据,系统得预热,运行基准测试,以及记录结果。
?
你经常多次的运行基准测试。到底运行多少次,这和你计分方式和结果的重要性有很大关系。如果你要最准确的确定的事情。你需要更多次的运行基准测试。有许多好的方式有助于得到更准确的结果,如平均所有结果或者运行5次基准测试,取其中最好的3次取平均。可以精确的获得你想要的。你可能应用统计学来分析结果,找出可信的区间等等,但是往往你并不需要这个精确级别。如果这些结果可以令你满意,你可以简单的运行基准测试以及看这些结果的变化。如果结果变化非常大,那么只有多次运行或者运行时间更长。这样才能降低结果的差异。
?
一旦你有了结果,你需要分析它们-那就是把数量转换为知识。目标就是解决问题。比较理想的是,得到结果如:相同的延迟下升级到4个CPU可以提高50%的吞吐量。索引能使查询更迅速。
?
你怎样完全分析透数据取决于你怎样收集结果。你可能应该写脚本去分析结果,不仅仅能降低工作量,也可以自动运行基准测试:重复和记录。
?
?
?