相关命令和工具
(1)nm a.out|grep compare
(2)g++ -O2 -Winline main.cpp
Winline对含有inline关键字的而没有进行inline进行警告
(3)perf
- 统计基准程序:
(1)通过随机生成16M个整数,进行排序,统计排序所需要要的时间,
(2)基于Linux平台,GCC,参数选项O2级优化
g++ -O2 main.cpp
程序如下:
#include <stdlib.h> #include <vector> #include <sys/stat.h> #include <sys/timeb.h> inline bool compare(int a, int b) { return a < b; } struct Functor { bool operator()(int a, int b) const { return a < b; } }; int main(int argc,char*argv[]) { std::vector<int> vec1; std::vector<int> vec2; size_t count = 16*1024*1024; vec1.reserve(count); vec2.reserve(count); srand(0XDeadBeaf); long long t1=0; long long t2=0; //for(int j=0;j<16;j++) { vec1.clear(); vec2.clear(); for(size_t i=0;i<count;i++) { int rd = rand(); vec1.push_back(rd); vec2.push_back(rd); } clock_t t2_start=clock(); std::sort(vec2.begin(), vec2.end(), Functor()); clock_t t2_end = clock(); clock_t t1_start=clock(); std::sort(vec1.begin(), vec1.end(), compare); clock_t t1_end=clock(); t1 += t1_end-t1_start; t2 += t2_end-t2_start; } printf("1 cost:%d\n2 cost:%d\n",(t1)/(CLOCKS_PER_SEC/1000),(t2)/(CLOCKS_PER_SEC/1000)); getchar(); return 0; }
- 统计结果
1 cost:4090
2 cost:3030
1为使用内联函数方式,2为Functor方式
- 基于perf程序性能分析
统计使用方式如下:
(1)统计性能到文件中(其余参数,man perf,这里都忽略)
$>perf record ./a.out
(2)显示分析报告
$>perf report
基于该统计结果进行分析如下:
- 使用函数compare方式
0.65 : 401209: callq *%rbx a 4.03 : 40120b: test %al,%al a 0.00 : 40120d: lea 0x4(%r12),%rdx a 0.00 : 401212: jne 401200 <void std::__introsort_loop<__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, long, bool (*)(int` 7.04 : 401214: mov 0x8(%rsp),%r15 a 7.36 : 401219: sub $0x4,%r15 a 0.71 : 40121d: nopl (%rax) a 9.30 : 401220: mov %r15,0x8(%rsp) a 14.59 : 401225: mov (%r15),%esi a 3.03 : 401228: sub $0x4,%r15 a 0.00 : 40122c: mov 0x4(%rsp),%edi a 1.97 : 401230: callq *%rbx a 5.10 : 401232: test %al,%al a 0.00 : 401234: jne 401220 <void std::__introsort_loop<__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, long, bool (*)(inta 7.88 : 401236: cmp 0x8(%rsp),%r12 a 0.00 : 40123b: jae 401255 <void std::__introsort_loop<__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, long, bool (*)(inta 9.52 : 40123d: mov 0x8(%rsp),%rcx
- Functor方式
11.71 : 400e50: add $0x4,%r13 a
4.69 : 400e54: mov 0x0(%r13),%edx a
8.13 : 400e58: cmp %edx,%edi a
0.00 : 400e5a: jg 400e50 <void std::__introsort_loop<__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, long, Functor>(__ga
9.77 : 400e5c: cmp %ecx,%edi a
5.07 : 400e5e: lea -0x4(%rax),%r8 `
0.92 : 400e62: jge 400e7d <void std::__introsort_loop<__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, long, Functor>(__ga
4.31 : 400e64: sub $0x8,%rax a
1.95 : 400e68: nopl 0x0(%rax,%rax,1) a
9.50 : 400e70: mov (%rax),%ecx a
10.15 : 400e72: mov %rax,%r8 a
0.04 : 400e75: sub $0x4,%rax a
0.08 : 400e79: cmp %ecx,%edi a
0.00 : 400e7b: jl 400e70 <void std::__introsort_loop<__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, long, Functor>(__ga
11.06 : 400e7d: cmp %r13,%r8 a
5.04 : 400e80: jbe 400e9e <void std::__introsort_loop<__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, long, Functor>(__ga
4.01 : 400e82: mov %ecx,0x0(%r13) a
6.98 : 400e86: add $0x4,%r13 a
0.04 : 400e8a: mov %edx,(%r8) a
3.01 : 400e8d: mov -0x4(%r8),%ecx a
0.57 : 400e91: mov 0x0(%r13),%edx
- 总耗时概览
41.09% a.out a.out [.] void std::__introsort_loop<__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, long, bool (*)(int, int)>(__` 34.57% a.out a.out [.] void std::__introsort_loop<__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, long, Functor>(__gnu_cxx::__a 12.15% a.out a.out [.] main a 7.64% a.out a.out [.] compare(int, int)
对比1,2,红色部分;可以看出,在std:sort中,compare并不能被内联,虽然已经声明为内联。
callq %rbx即为调用compare函数,因此,造成了性能影响。
- 结论:
(1)Functor函数对象比内联函数,在std::sort这种复杂的函数中(存在递归,循环),效率更高。
(2)内联,由编译器决定,通常不影响性能