资源预览内容
亲,该文档总共2页全部预览完了,如果喜欢就下载吧!
资源描述
l gprof 的适用范围gprof可以用来分析系统在运行时各函数调用的次数,耗时等情况,可以方便地帮助我们定位系统的瓶颈,同时也能让我们知道对程序的那个位置就行优化能够带来尽可能大的性能提升。gprof 优化尤其适用于CPU、内存密集性的应用模块。 l gprof的安装使用目前我们的linux主机上大多都安装了gprof,详细的参数等可以通过man gprof查看。需要重点指出的是,目前我们线上的gprof对多线程的支持不好,直接调用只能得到主线程的相关调用情况。根据相关资料,原因为gprof采用ITIMER_PROF 信号,在多线程内,只有主线程才能响应该信号。为此,需要做一些额外的工作。使用提供的gprof-helper.c,将其编译为so库, 命令为:gcc -shared -fPIC gprof-helper.c -o gprof-helper.so -lpthread -ldl这个库的作用实际上实现一个 pthread_create 的钩子程序,这样我们在调用 pthread_create函数的时候就会调用到这个库中提供的pthread_create 的函数,从而实现在多线程情况下统计运行时的相关信息。在实际使用中,方法比较简单,在我们自己的程序的makefile文件中,加上编译的选项 -pg,并加上那个动态链接库。如gcc -pg imbs_main.cpp ./gprof-helper.so $(INCLUDE) $(LDFLAGS) $(LDLIBS)。这样在编译后会生成一个a.out 文件。这个文件就是包含了相关统计功能的可执行文件,和我们正常编译的程序在对外行为上是完全一致的。参考资料: http:/blog.csdn.net/baqiao10/articles/.aspx 程序运行并“正常”退出后,会生成一个gmon.out文件,这个就是运行时的统计文件。使用命令gprof -b a.out gmon.out 就可以将最终我们readable的信息输出来。这些信息可以作为我们优化的依据。 注意: 上面提到的“正常”退出是指程序是按照自身的运行逻辑正常退出的,如果直接killall -9 是不能得到统计结果的。而我们通常的程序都是在循环中长时间运行,所以,实际中采用了相应 SIGTERM信号的方式,使用killall -s 15 ,发送SIGTERM信号给程序,程序中会有相应的函数捕捉该信号,捕捉到该信号后,置一个退出标记,这样我们就可以控制程序按照既定的逻辑在处理完一次完整的工作后正常的退出。 这又引出了另一个问题,实际上我们现在上线程序,重启程序的时候,通常都是使用killall -9来停止原有程序的。这实际上是存在较大风险的,举例来说,如果程序在执行时存在一些持久化的操作,比如写磁盘,同时,写磁盘操作是多次完成,比如先写数据、再写索引等,这应该是一个在逻辑上的原子操作,那么killall -9的随机性可能破坏其原子性,从而造成潜在的数据不一致,如在我们常用的transfer中就存在这种数据不一致的隐患。虽然出现的概率不是很高,但是,长期的积累这种不一致性是会慢慢体现出来的。 l 常见的优化手段关于具体的优化,这个可能就不是一点篇幅就能写得下了,提一些常见的经验供参考。 1. 循环次数很多的循环体内部, 这种优化是收益最高的一种优化之一。循环体内部节约n条指令,最终收益将乘以循环次数。常见的如将循环体内不改变的变量移动到循环体外,多重循环嵌套时的顺序问题。 2. 优化函数调用。这是优化提高非常明显的一种方式,常见的方式如函数inline,这样可以节约大量的函数调用的开销,避免多次的压栈出栈。需要注意的是,如果makefile中不指定至少-O优化,即使声明为inline函数,编译器也不会进行函数内联。 3. 优化内存寻址,避免重复的内存寻址。 4. 优化cpu流水线的分支预测的成功率。比如,如果当前存在有 ifelse ifelse语句,将满足概率最高的条件放到靠前的位置不仅能减少判断和跳转指令的执行,还有利于cpu在流水作业时分支预测的成功率,提高指令的流水化。 3和4单独优化的提升不会很大,但是如果是在大量的循环体内部,提升就会被放大很多倍。
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号