性能调优攻略

关于性能优化这是一个比较大的话题,在《由12306.cn谈谈网站建设性能技术》中我从业务和设计上说过一些可用的技术以及那些技术的优缺点,今天,想从一些技术细节上谈谈性能优化,主要是一些代码级别的技术和方法。本文的东西是我的一些经验和知识,并不一定全对,希望大家指正和补充。
在开始这篇文章之前,大家可以移步去看一下酷壳以前发表的《代码优化概要》,这篇文章基本上告诉你——要进行优化,先得找到性能瓶颈! 但是在讲如何定位系统性能瓶劲之前,请让我讲一下系统性能的定义和测试,因为没有这两件事,后面的定位和seo优化无从谈起。
一、系统性能定义
让我们先来说说如何什么是系统性能。这个定义非常关键,如果我们不清楚什么是系统性能,那么我们将无法定位之。我见过很多朋友会觉得这很容易,但是仔细一问,其实他们并没有一个比较系统的方法,所以,在这里我想告诉大家如何系统地来定位性能。 总体来说,系统性能就是两个事:
1. throughput ,吞吐量。也就是每秒钟可以处理的请求数,任务数。
2. latency, 系统延迟。也就是系统在处理一个请求或一个任务时的延迟。
一般来说,一个系统的性能受到这两个条件的约束,缺一不可。比如,我的系统可以顶得住一百万的并发,但是系统的延迟是2分钟以上,那么,这个一百万的负载毫无意义。系统延迟很短,但是吞吐量很低,同样没有意义。所以,一个好的系统的性能测试必然受到这两个条件的同时作用。 有经验的朋友一定知道,这两个东西的一些关系:
• throughput越大,latency会越差。因为请求量过大,系统太繁忙,所以响应速度自然会低。
• latency越好,能支持的throughput就会越高。因为latency短说明处理速度快,于是就可以处理更多的请求。
二、系统性能测试
经过上述的说明,我们知道要测试系统的性能,需要我们收集系统的throughput和latency这两个值。
• 首先,需要定义latency这个值,比如说,对于网站系统响应时间必需是5秒以内(对于某些实时系统可能需要定义的更短,比如5ms以内,这个更根据不同的业务来定义)
• 其次,开发性能测试工具,一个工具用来制造高强度的throughput,另一个工具用来测量latency。对于第一个工具,你可以参考一下"十个免费的web压力测试工具",关于如何测量latency,你可以在代码中测量,但是这样会影响程序的执行,而且只能测试到程序内部的latency,真正的latency是整个系统都算上,包括操作系统和网络的延时,你可以使用wireshark来抓网络包来测量。这两个工具具体怎么做,这个还请大家自己思考去了。
• 最后,开始性能测试。你需要不断地提升测试的throughput,然后观察系统的负载情况,如果系统顶得住,那就观察latency的值。这样,你就可以找到系统的最大负载,并且你可以知道系统的响应延时是多少。
再多说一些,
• 关于latency,如果吞吐量很少,这个值估计会非常稳定,当吞吐量越来越大时,系统的latency会出现非常剧烈的抖动,所以,我们在测量latency的时候,我们需要注意到latency的分布,也就是说,有百分之几的在我们允许的范围,有百分之几的超出了,有百分之几的完全不可接受。也许,平均下来的latency达标了,但是其中仅有50%的达到了我们可接受的范围。那也没有意义。
• 关于性能测试,我们还需要定义一个时间段。比如:在某个吞吐量上持续15分钟。因为当负载到达的时候,系统会变得不稳定,当过了一两分钟后,系统才会稳定。另外,也有可能是,你的系统在这个负载下前几分钟还表现正常,然后就不稳定了,甚至垮了。所以,需要这么一段时间。这个值,我们叫做峰值极限。
• 性能测试还需要做soak test,也就是在某个吞吐量下,系统可以持续跑一周甚至更长。这个值,我们叫做系统的正常运行的负载极限。
性能测试有很多很复要的东西,比如:burst test等。 这里不能一一详述,这里只说了一些和性能调优相关的东西。总之,性能测试是一细活和累活。
三、定位性能瓶颈
有了上面的铺垫,我们就可以测试到到系统的性能了,再调优之前,我们先来说说如何找到性能的瓶颈。我见过很多朋友会觉得这很容易,但是仔细一问,其实他们并没有一个比较系统的方法。
3.1)查看操作系统负载
首先,当我们系统有问题的时候,我们不要急于去调查我们代码,这个毫无意义。我们首要需要看的是操作系统的报告。看看操作系统的cpu利用率,看看内存使用率,看看操作系统的io,还有网络的io,网络链接数,等等。windows下的perfmon是一个很不错的工具,linux下也有很多相关的命令和工具,比如:systemtap,latencytop,vmstat, sar, iostat, top, tcpdump等等 。通过观察这些数据,我们就可以知道我们的软件的性能基本上出在哪里。比如:
1)先看cpu利用率,如果cpu利用率不高,但是系统的throughput和latency上不去了,这说明我们的程序并没有忙于计算,而是忙于别的一些事,比如io。(另外,cpu的利用率还要看内核态的和用户态的,内核态的一上去了,整个系统的性能就下来了。而对于多核cpu来说,cpu 0 是相当关键的,如果cpu 0的负载高,那么会影响其它核的性能,因为cpu各核间是需要有调度的,这靠cpu0完成)
2)然后,我们可以看一下io大不大,io和cpu一般是反着来的,cpu利用率高则io不大,io大则cpu就小。关于io,我们要看三个事,一个是磁盘文件io,一个是驱动程序的io(如:网卡),一个是内存换页率。这三个事都会影响系统性能。
3)然后,查看一下网络带宽使用情况,在linux下,你可以使用iftop, iptraf, ntop, tcpdump这些命令来查看。或是用wireshark来查看。
4)如果cpu不高,io不高,内存使用不高,网络带宽使用不高。但是系统的性能上不去。这说明你的程序有问题,比如,你的程序被阻塞了。可能是因为等那个锁,可能是因为等某个资源,或者是在切换上下文。
通过了解操作系统的性能,我们才知道性能的问题,比如:带宽不够,内存不够,tcp缓冲区不够,等等,很多时候,不需要调整程序的,只需要调整一下硬件或操作系统的配置就可以了。
3.2)使用profiler测试
接下来,我们需要使用性能检测工具,也就是使用某个profiler来差看一下我们程序的运行性能。如:java的jprofiler/tptp/codepro profiler,gnu的gprof,ibm的purifyplus,intel的vtune,amd的codeanalyst,还有linux下的oprofile/perf,后面两个可以让你对你的代码优化到cpu的微指令级别,如果你关心cpu的l1/l2的缓存调优,那么你需要考虑一下使用vtune。 使用这些profiler工具,可以让你程序中各个模块函数甚至指令的很多东西,如:运行的时间 ,调用的次数,cpu的利用率,等等。这些东西对我们来说非常有用。
我们重点观察运行时间最多,调用次数最多的那些函数和指令。这里注意一下,对于调用次数多但是时间很短的函数,你可能只需要轻微优化一下,你的性能就上去了(比如:某函数一秒种被调用100万次,你想想如果你让这个函数提高0.01毫秒的时间 ,这会给你带来多大的性能)
使用profiler有个问题我们需要注意一下,因为profiler会让你的程序运行的性能变低,像purifyplus这样的工具会在你的代码中插入很多代码,会导致你的程序运行效率变低,从而没发测试出在高吞吐量下的系统的性能,对此,一般有两个方法来定位系统瓶颈:
1)在你的代码中自己做统计,使用微秒级的计时器和函数调用计算器,每隔10秒把统计log到文件中。
2)分段注释你的代码块,让一些函数空转,做hard code的mock,然后再测试一下系统的throughput和latency是否有质的变化,如果有,那么被注释的函数就是性能瓶颈,再在这个函数体内注释代码,直到找到最耗性能的语句。
四、常见的系统瓶颈
下面这些东西是我所经历过的一些问题,也许并不全,也许并不对,大家可以补充指正,我纯属抛砖引玉。关于系统架构方面的性能调优,大家可移步看一下《由12306.cn谈谈网站性能技术》,关于web方面的一些性能调优的东西,大家可以看看《web开发中需要了解的东西》一文中的性能一章。我在这里就不再说设计和架构上的东西了。
一般来说,性能优化也就是下面的几个策略:
• 用空间换时间。各种cache如cpu l1/l2/ram到硬盘,都是用空间来换时间的策略。这样策略基本上是把计算的过程一步一步的保存或缓存下来,这样就不用每次用的时候都要再计算一遍,比如数据缓冲,cdn,等。这样的策略还表现为冗余数据,比如数据镜象,负载均衡什么的。
• 用时间换空间。有时候,少量的空间可能性能会更好,比如网络传输,如果有一些压缩数据的算法(如前些天说的"huffman 编码压缩算法" 和 "rsync 的核心算法"),
上一个:在开始设计新网站之前要考虑的19个因素
下一个:设计师如何对抗精神超载
南澳网站建设,南澳做网站,南澳网站设计