前段时间一直在做服务器程序的优化。分析工具用了很多,AQtime、PurifyPlus、valgrind,最终找到了vtune。
vtune9 支持windows程序的性能分析。包括执行时间、lock and wait、线程竞争、io分析等等。通过它可以直观的看到整个系统上所有进程的执行时间,以及进程内部每个线程、线程内部各个模块的执行时间以及它们的比例关系。还可以分析线程之间的竞争关系,以及函数之间的调用图,对比源代码快速定位系统的性能瓶颈。新版Vtune(Intel Amplifier XE 2011)易用性更好,能对比两次分析的结果,给出差距分析报告。对比优化效果非常方便。
对于linux程序,可以在linux主机上安装rdc(remote data collect)。通过windows下的vtune程序远程操控rdc进行数据采集。采集结束以后,由rdc把结果传到windows客户端。这样就可以在window下查看统计结果,对比源代码,分析系统瓶颈了。新版Vtune(Intel Amplifier XE 2011)提供linux下的gui界面,但是不支持远程操控。采集的数据也可以在windows下查看。
我们的优化对象是一个分布式系统,服务器进程部署在不同的物理机器上,服务器通过业务网关和客户端进行通信。
在早期的优化过程中,通过vtune的分析,我们发现:
1. 系统中存在不必要的锁竞争、大量的new/delete是系统瓶颈之一。
2. 流量接近网络的极限(100Mbps),客户端经常掉线。
3. 高负载下,业务网关的cpu占用接近100%(多核cpu,单核为100%)。
为此,我们对上述问题进行了优化:
1. 首先,去掉不必要的锁,减少new和delete。
结果发现,在优化new和delete以后,同等负载下,业务网关的cpu占用率从100% 降到了15~20%。
2. 在网络传输时,启动压缩机制,降低流量。
采用网络压缩以后,网络流量下降到30Mbps,系统的整体性能非但没有下降,反而明显上升。这说明在用cpu兑换网络io的过程中,压缩的时间明显要小于70Mbps的网络io时间。
随着整体性能的提升,网络流量不再是系统的瓶颈,掉线减少了,上层业务跑得更快了。
在提高负载后,我们用vtune分析再次进行分析后发现,在目标进程里,cpu占用率达到300%(单核为100%),发送线程和业务线程的占了整个进程cpu时间的70%以上,而网络线程(1个)的cpu占用时间要明显高于其他业务线程。一旦业务负载上升,网络处理线程仍然是系统的瓶颈。
面对这个新问题,我们把网络线程拆分成多个,每个网络线程对应1个或者多个网关,希望提高服务器的网络吞吐能力。
改造以后,cpu 占用率基本保持不变,但是网络流量在30Mbps的基础上又有上升。这个结果验证了我们之前的判断,随着网络收发能力的提高,业务线程可以在同样的时间里处理更多的客户端请求,网络流量自然也就上升了。
vtune的分析数据也验证了我们的结论。单个网络线程明显低于业务线程(约占60%),但是2个的总和要明显高于单个业务线程。网络收发已经不是系统的主要瓶颈。
下一步的优化目标就是要提高业务线程的处理能力。
经过这次的优化实践,总结起来有这样几点经验教训:
1. 俗话说,工欲善其事必先利其器,vtune是性能分析的好工具。
2. new/delete 的性能是低下的,这在effective c++ 和c++高性能程序里已经阐述的很清楚了。
2. 网络的io速度远低于cpu执行速度,用cpu时间换网络io是值得的。
3. 在多核cpu上开发程序,需要充分考虑生产线程和消费线程的比例关系。只有双方的处理能力基本持平,才能发挥多核的优势,实现cpu和业务承载量的线性扩展。如果硬件环境不确定,就要求生产线程、消费线程的数量可调。
以下转载自:
【使用Intel Thread Profiler查看Parallel.For性能】
http://www.cnblogs.com/daizhj/archive/2009/01/13/1371150.html
Intel Thread Profiler是intel公司发布的一个优化线程的可视化工具。它有助于您了解线程应用的结构,
最大限度提升应用性能。同时可以快速准确找到影响程序执行时间的代码位置。今天的文章就是使用该工具
来对比一下使用Microsoft Parallel Extensions Jun08 CTP 中的Parallel.For与我们平时使用的for语句在
CPU运行时性能参数的一些不同之处。
这里有必要说明一下图中红框中的四个指标:
Processor Queue Length:是指处理队列中的线程数。即使在有多个处理器的计算机上处理器时间也会有一个单队列。
不象磁盘计数器,这个计数器仅计数就绪的线程,而不计数 运行中的线程。如果处理器队列中总是有两个以上的线程通常表
示处理器堵塞。这个计数器仅显示上一次观察的值;而不是一个平均值。
Context Switches per Second:每秒线程切换次数, 在有的书中翻译成上下文切换,实际含义是任务切换,或CPU寄存
器内容切换。当多任务内核决定运行另外的任务时,它保存正在运行任务的当前状态(Context),即CPU寄存器中的全部内
容。这些内容保存在任务的当前状况保存区(Task’s Context Storage area),也就是任务自己的栈区之中。入栈工作完
成以后,就是把下一个将要运行的任务的当前状况从该任务的栈中重新装入CPU的寄存器,并开始下一个任务的运行。这个过
程叫做任务切换。任务切换过程增加了应用程序的额外负荷。CPU的内部寄存器越多,额外负荷就越重。做任务切换所需要的
时间取决于CPU有多少寄存器要入栈。更多的内容参见这篇文章, 还有一篇比较有意思的文章是蔡学庸先生写的,链接在这里
Privileged Time:(CPU内核时间)是在特权模式下处理线程执行代码所花时间的百分比。如果该参数值和"physical
Disk"参数值一直很高,表明I/O有问题。可考虑更换更快的硬盘系统。另外设置Tempdb in RAM,减低"max async IO",
"max lazy writer IO"等措施都会降低该值。
Processor Time: 指处理器执行非闲置线程时间的百分比。这个计数器设计成用来作为处理器活动的主要指示器。它通
过在每个范例间隔中衡量处理器用于执行闲置处理线程的时间,并且用100%减去该值得出。(每个处理器有一个闲置线程,
该线程在没有其它线程可以运行时消耗周期)。可将其视为范例间隔用于做有用工作的百分比。
联系客服