首先看如下的程序;
#include <stdio.h> #include <stdlib.h> int buff[99999999]; int count = 0; void swap(int i, int j){ int t = buff[i]; buff[i] = buff[j]; buff[j] = t; } int main(){ FILE* fp = fopen("sort_set", "r"); while(fscanf(fp,"%d", &buff[count++])!=EOF && count <50000); fclose(fp); int i=0; int j=0; for(i=1;i<50000;i++){ for(j=i;j>0&&buff[j-1]>buff[j]; j--){ swap(j-1, j); //int t = buff[j-1]; //buff[j-1] = buff[j]; //buff[j] = t; } } }
文件sort_set中保存了99999999个随机的整数,作为排序算法的测试集;
排序程序对测试集中的5万个整数进行排序。
(1)采用swap函数的运行时间以及通过内联方式运行所需的时间
real 0m6.154s user 0m6.136s sys 0m0.008s
real 0m4.155s user 0m4.140s sys 0m0.004s
由于swap函数处在最内层循环,由于函数调用导致的开销占据了运行时间的很大部分。
通过gprof分析,可以发现swap函数被调用的次数
Flat profile: Each sample counts as 0.01 seconds. % cumulative self self total time seconds seconds calls ns/call ns/call name 55.95 3.60 3.60 main 41.20 6.25 2.65 625771697 4.23 4.23 swap 3.77 6.49 0.24 frame_dummy Call graph granularity: each sample hit covers 2 byte(s) for 0.15% of 6.49 seconds index % time self children called name <spontaneous> [1] 96.3 3.60 2.65 main [1] 2.65 0.00 625771697/625771697 swap [2] ----------------------------------------------- 2.65 0.00 625771697/625771697 main [1] [2] 40.8 2.65 0.00 625771697 swap [2] ----------------------------------------------- <spontaneous> [3] 3.7 0.24 0.00 frame_dummy [3] ----------------------------------------------- Index by function name [3] frame_dummy [1] main [2] swap
题外话,gprof是如何获取到程序运行的profile信息的,以及结果中frame_dummy是个什么东东??
系统在运行main函数之前,其实做了好多的工作,其中就包括调用gmon_start例程,该例程会统计程序的运行情况。frame_dummy用于传入elf文件中的.eh_frame和.bss,并对其注册。
(2)通过消除函数调用以及从新频繁执行的语句,将程序优化为:
#include <stdio.h> #include <stdlib.h> int buff[99999999]; int count = 0; int main(){ FILE* fp = fopen("sort_set", "r"); while(fscanf(fp,"%d", &buff[count++])!=EOF && count <50000); fclose(fp); int i=0; int j=0; for(i=1;i<50000;i++){ int t = buff[i]; for(j=i;j>0&&buff[j-1]>buff[j]; j--){ buff[j] = buff[j-1]; buff[j-1] = t; } } }
real 0m3.520s user 0m3.512s sys 0m0.000s