分类:
2011-10-26 16:09:24
本文的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可以让代码更好看。