Chinaunix首页 | 论坛 | 博客
  • 博客访问: 8130779
  • 博文数量: 159
  • 博客积分: 10424
  • 博客等级: 少将
  • 技术积分: 14615
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-14 12:45
个人简介

啦啦啦~~~

文章分类
文章存档

2015年(5)

2014年(1)

2013年(5)

2012年(10)

2011年(116)

2010年(22)

分类: C/C++

2010-07-14 13:24:05

本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
作者:gfree.wind@gmail.com
博客:linuxfocus.blog.chinaunix.net
    

最近遇到了一个问题,在我修改代码 时,发现原有函数的参数个数已经达到了8个,而为了加入新的功能的话,参数的个数会增长到10多个。在我看来,十几个参数的函数不是什么好风格。所以我选 择创建一个新的structure,structure中包含所有的参数,然后将structure的地址作为新的参数,这样可以将输入参数的个数减小为 一个。同时,使用structure,以后再添加新的参数,不需要该函数的接口了。但为了使用structure,在调用函数前,无疑要创建一个 structure,并用以前的参数,对所有的成员变量赋值。

于是,在code review的过程中,同事认为,不应该使用structure,因为引入了没有必要的赋值操作,影响性能——我们的产品是追求性能的产品。所以在这一块关注较多。尽管只是36字节的赋值,但是能避免就避免。还是直接添加更多的参数。

由于我英语口语不太好,所以讨论的过程中,自然居于下风,况且他还是leader,那就他怎么说就怎么做了。

但 是我认为,使用structure固然会引入不必要的赋值,但是使用多个参数,在传递给调用函数时,赋值依然是避免不了的,无论如何也要把值复制导栈上。 而传递structure地址的时候,只需要复制一个值。所以我认为当有多个函数的时候,在传递参数方面,使用structure地址来代替多个参数,有 着更高的性能。

下面看我做的实验。

第一个程序,每次调用函数都是直接传递3个参数

#include

void test(int a, int b, int c, int nest_cnt)
{
        if (nest_cnt) {
                test(a, b, c, --nest_cnt);
        }
}

int main()
{
        int a,b,c;
        a = 1;
        b = 2;
        c = 3;

        int i;
        for (i = 0; i < 100000000; ++i)
                test(a,b,c, 1);

}

第二个程序,使用structure代替多个参数

#include

typedef struct {
        int a;
        int b;
        int c;
} MY_TEST_S;

void test(MY_TEST_S* t, int nest_cnt)
{
        if (nest_cnt) {
                test(t, --nest_cnt);
        }
}

int main()
{
        int a,b,c;
        a = 1;
        b = 2;
        c = 3;

        int i;
        for (i = 0; i < 100000000; ++i) {
                MY_TEST_S t;
                t.a = a;
                t.b = b;
                t.c = c;
                test(&t, 1);
        }

}

为了避免其他影响,test函数什么都不做,只是继续嵌套调用自己,直到指定个数。且不使用任何编译参数。

下面看测试结果:

当嵌套个数为1时, time ./my_test1 = 1.535s,time ./my_test2=1.850s

这个是正常的,因为只有一次函数调用时,多参数的赋值次数只有3次(参数的个数),而structure有4次(3次赋值给structure的成员变量,和1次参数);

当嵌套个数为2时,time ./my_test1 = 1.711s,time ./my_test2 = 1.552s

这时,structure的程序性能已经超过了传递多参数。因为赋值次数已经要少于程序1了。

当嵌套次数为10时,time ./my_test1=7.256s,time ./my_test2=6.831s

 

到 这里,说明使用structure来代替传递多参数时,在函数调用方面,copy的代价structure甚至于要优于多参数。但是这并不代表使用 structure有着更好的性能,因为在使用structure 的成员时,不得不进行一次寻址的操作,因为c语言中的t->a,CPU必须使用t的地址,先找到a的地址,才能对a进行操作。

下面把程序稍微改一下,在test函数中,对structure中的成员变量进行操作。

-----------------------------1 -----------------------------

#include

void test(int a, int b, int c, int nest_cnt)
{
        ++a;
        ++b;
        ++c;
        if (nest_cnt) {
                test(a, b, c, --nest_cnt);
        }
}

int main()
{
        int a,b,c;
        a = 1;
        b = 2;
        c = 3;

        int i;
        for (i = 0; i < 100000000; ++i)
                test(a,b,c, 1);

}
------------------------------2 ------------------------------
#include

typedef struct {
        int a;
        int b;
        int c;
} MY_TEST_S;

void test(MY_TEST_S* t, int nest_cnt)
{
        ++t->a;
        ++t->b;
        ++t->c;
        if (nest_cnt) {
                test(t, --nest_cnt);
        }
}

int main()
{
        int a,b,c;
        a = 1;
        b = 2;
        c = 3;

        int i;
        for (i = 0; i < 100000000; ++i) {
                MY_TEST_S t;
                t.a = a;
                t.b = b;
                t.c = c;
                test(&t, 1);
        }

}

-----------------------------------------------------------------

嵌套次数直接使用5次,来看看结果

time ./my_test1 = 4.805s

time ./my_test2 = 5.949s

可见,structure在参数传递方面的优势,被使用其成员变量时,不得不进行2次操作给抵消了。导致程序2的性能还要差于程序1。

所以哪种性能更好,还要具体情况,具体分析了。看看函数中是否对structure的成员有操作。

 

最后,在我看来,在对性能追求不是到了比较极致的地步,使用structure可以让代码更好看。

阅读(5342) | 评论(3) | 转发(2) |
给主人留下些什么吧!~~

lajijifang2011-05-18 20:01:28

我认同你的观点.内存寻址是恒定的,而调用函数时,压栈的次数会严重影响性能

GFree_Wind2011-04-29 11:41:51

ghoststears: 函数都有十个参数了,这个函数应该重写了。
分成多个函数来写吧。

个人观点:如果仅仅是为了给参数传递定义个 structure ,是不必要的。.....
有时候,这么多参数在复杂的应用是难免的——当然也许是模块接口定义得不太好。所以才需要一个structure

ghoststears2011-04-29 11:16:11

函数都有十个参数了,这个函数应该重写了。
分成多个函数来写吧。

个人观点:如果仅仅是为了给参数传递定义个 structure ,是不必要的。