• 2007-08-30

    使用gprof剖析代码解决性能问题 - [LBE]

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://gosman.blogbus.com/logs/8015225.html

    原文:Use gprof to check your codes for performance issues
    作者:mysurface
    译者:gosman(lianmingchang2008#gmail.com)
    来自:http://gosman.blogbus.com
    版本:V 1.0.0
    时间:2007-8-30

    通过阅读IBM DevelopWorks上的使用 GNU profiler 来提高代码运行速度,我掌握了使用gprof来分析代码的性能瓶颈,以减轻我工作的技术。下面就来分享一下我的经验。

    我们先看看GNU profiler工作的几个简单步骤。

    为了使用gprof,只需在用gcc编译C/C++代码时加上-pg选项。假设要编译的源代码是gp-test.c。

    gcc -pg -g2 -o gp-test{,.c}

    -pg是启用gprof,-g2设置调试模式为2,-o指定二进制输出,我使用了大括号扩展来减少我的输入。

    接着运行可执行文件,将产生gmon.out。

    ./gp-test

    有了gmon.out,我们就可以使用gprof来剖析我们的代码。

    gprof gp-test gmon.out > result.txt 

    我倾向于把输出保存为一个文件'result.txt',以利于将来的比较和分析。

    让我们举一个C例子代码,试着找到关键点。

    #include
    int twoD[10000][10000]={0};
    int update_d1()
    {
    int i,k=0;
    for (i=0;i<10000;i++)
    twoD[i][1]=k++;
    }
    int update_d2()
    {
    int i,k=0;
    for (i=0;i<10000;i++)
    twoD[1][i]=k++;
    }
    int main(int argc, char * argv[])
    {
    int i,j,k=0;
    if (argc!=2)
    return -1;
    if (*(argv[1])=='1')
    update_d1();
    else if (*(argv[1])=='2')
    update_d2();
    else
    printf("\nInvalid value %s\n",argv[1]);
    return 1;
    }

    函数update_d1()和update_d2()循环一样的次数来访问二维数组。设这二维数组为twoD[row][column],update_d1()访问行(row),update_d2()访问列(column)。我们发现这两个函数的运行时间差很大。让我们用gprof剖析一下吧。

    gcc -pg -g -o gp-test{,.c}
    ./gp-test 1
    gprof gp-test gmon.out > t1
    ./gp-test 2
    gprof gp-test gmon.out > t2

    观察剖析结果:

    using update_d1() :
    % cumulative self self total
    time seconds seconds calls ms/call ms/call name
    100.52 0.06 0.06 1 60.31 60.31 update_d1
    using update_d2() :
    % cumulative self self total
    time seconds seconds calls Ts/call Ts/call name
    0.00 0.00 0.00 1 0.00 0.00 update_d2

    update_d1()花费0.06秒,update_d2()少于0.01秒,为什么呢?

    让我们再看看这个二维数组twoD[row][column]。这个数组在物理上映射为一整块内存,而不是按行列排列。这内存块以0行1列开始,而第一行第一列实际是第10001块。

    想象一下update_d1()怎样访问内存?为了访问每行,你需要越过10000块,而update_d2()可以直接访问那10000块。这就是延迟的原因。


    收藏到:Del.icio.us