Linux代码性能检测利器(二)--OProfile之代码分析示例

21 篇文章 0 订阅

https://i-blog.csdnimg.cn/blog_migrate/7df1ca56f70e3127c0ea9e00986f70f2.png

对于做应用级别(相对内核开发)的开发,如果只想快速找到代码性能瓶颈而对OProfile的工作原理不感兴趣,只看该示例应该就足够了。


假如我们的代码文件是/home/leo/oprofile_test/main.cpp,内容是:

  1. #include <stdio.h>  
  2.   
  3. #include <unistd.h>  
  4.   
  5. #include <string.h>  
  6.   
  7.    
  8.   
  9. class FileOp  
  10.   
  11. {  
  12.   
  13.          public:  
  14.   
  15.                    FileOp(char *file)  
  16.   
  17.                    {  
  18.   
  19.                             strcpy(m_fileName, file);  
  20.   
  21.                             m_buff = new char[1024];  
  22.   
  23.                             memset(m_buff, 0, 1024);  
  24.   
  25.                    }  
  26.   
  27.    
  28.   
  29.                    ~FileOp()  
  30.   
  31.                    {  
  32.   
  33.                             delete []m_buff;  
  34.   
  35.                             m_buff = NULL;  
  36.   
  37.                    }  
  38.   
  39.    
  40.   
  41.                    void DoWork()  
  42.   
  43.                    {                           
  44.   
  45.                             FILE *fp = fopen(m_fileName, "r");  
  46.   
  47.                             if(!fp)  
  48.   
  49.                             {  
  50.   
  51.                                      return;  
  52.   
  53.                             }  
  54.   
  55.    
  56.   
  57.                             int count = 0;  
  58.   
  59.                             int i = 0;  
  60.   
  61.                             while(!feof(fp))  
  62.   
  63.                             {  
  64.   
  65.                                      fgets(m_buff, 1023, fp);  
  66.   
  67.                                      count = strlen(m_buff);  
  68.   
  69.                                      usleep(100);  
  70.   
  71.                                      fprintf(stderr, "The %ld has %ld characters!\n", ++i, count);  
  72.   
  73.                             }  
  74.   
  75.    
  76.   
  77.                             fclose(fp);  
  78.   
  79.                    }  
  80.   
  81.    
  82.   
  83.          private:  
  84.   
  85.                    char m_fileName[1024];  
  86.   
  87.                    char *m_buff;  
  88.   
  89. };  
  90.   
  91.    
  92.   
  93.    
  94.   
  95. int main(int argc, char **argv)  
  96.   
  97. {  
  98.   
  99.          if(argc != 2)  
  100.   
  101.          {  
  102.   
  103.                    return -1;  
  104.   
  105.          }         
  106.   
  107.           
  108.   
  109.          FileOp op(argv[1]);  
  110.   
  111.          op.DoWork();  
  112.   
  113.           
  114.   
  115.          return 0;  
  116.   
  117. }  

这段程序读取一个从命令行传递过来的一个文件,打印出每一行的字符数(这段代码是在64位机器上运行的)。

a)        使用“g++ -g main.cpp”将源代码编译成可执行程序

b)        使用“opcontrol --init”进行分析器初始化(启动分析器驱动模块)

c)        使用“opcontrol --setup --image=/home/leo/oprofile_test/a.out --event=CPU_CLK_UNHALTED:6000:0”和“opcontrol --no-vmlinux”设置分析器,如下图所示:



d)        使用“opcontrol --start”启动分析器



e)        运行程序,比如:“./a.out /var/log/messages.1

运行完成后,使用下面的命令获取分析结果。

a)        运行“opcontrol --dump”将采样数据送入分析器中

b)        运行“opreport -l”查看函数级的分析结果,如下图所示:



由图中可以看到FileOp::DoWork的采样百分比占到了99.0909%,说明大部分的CPU时间都是在此函数中。

c)        运行“opannotate --source”查看代码级别的分析结果,如下图所示:



   上图只是截取了关键的部分输出,从这个输出可以看到strlen这行占到了77%红色矩形中数字768表示在分析采样过程中改行采样数量为768,即每次设置的事件发生时查看运行所在的代码位置,发现一次就对改行的采样数加1,。77.5758代表改行采样数占所有采样数的77.5758%),说明这段代码的运行效率很低,找到了性能瓶颈,接下来的工作就是找函数替换strlen啦!(strlen的效率实在很低,尤其是当字符串很长的时候)

 

       OK,到此分析结果已经出来了,不过对于工程很大的情况,opreportopannotate的输出很多,这时候把分析结果导出到文件中就比较容易查看了,对于opreport,可以使用“opreport -l -o ./analysis.log”来讲分析结果输出到文件中,如下图所示:



而对于opannotate来讲,可以使用“opannotate --source --output-dir=/tmp/”来讲分析结果对应到相应的源代码文件中,如下图所示:



上面的命令的意思是将相应的打了标注的源代码文件放在“/tmp/”目录下,在该目录下,会根据源代码的文件结构生成相对应的文件结果,如图,在“/tmp/”目录下生成了“home/leo/oprofile_test”目录,与源代码的目录一致,而“main.cpp”就在该目录下,打开该目录下的“main.cpp”就可以查看每句代码对应的采样数据以及资源占用百分比了。

      

       用完了分析器,使用命令“opcontrol --stop”停止采样,命令“opcontrol --reset”清除当前会话中的采样数据,命令“opcontrol --shutdown”关闭分析器内核模块,“opcontrol --stop” 和命令“opcontrol --reset”是非常有必要的,因为不进行这两步下次在进行分析时就会受到这次结果的影响。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值