首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

【讨论】调用函数的运行时代价有关问题

2012-03-15 
【讨论】调用函数的运行时代价问题 最近写了一个分割文件的软件,是win32控制台的程序,软件能正常运行,然而却

【讨论】调用函数的运行时代价问题

最近写了一个分割文件的软件,是win32控制台的程序,软件能正常运行,然而却意外发现一个百思不得其解的问题,和大家讨论讨论。

先说一下我的分割文件原理:
在命令行下输入   “源文件名”和“分割的每个文件的大小”
检测源文件大小,再拿“源文件大小”除以“分割的每个文件的大小”得到分割后的文件个数,再逐一建立新文件,把源文件的数据copy到新文件中,以实现文件分割。
为了说明问题,举个简单的例子:
比如我要把一个大小为1000   KB的文件   test.txt   分割为300   KB大小的文件,则由于1000不能被300整除,因此应该把test.txt分割成4个文件,前三个大小为300   KB,最后一个是100   KB的。

因此创建前面的文件和创建最后一个文件必须区分开,前三次分割都可以这样完成:
//写成这种样式是为了说明问题
fread(s,1,300   KB,fp1);         //s是源文件数据中转数组,fp1是源文件指针
s[sizeof(s)]= '\0 ';                 //数组尾部置空
fwrite(s,1,300   KB,fp2);   //fp2是新建立的文件指针

而写最后一个文件必须这样:

fread(s,1,100   KB,fp1);        
s[sizeof(s)]= '\0 ';                
fwrite(s,1,100   KB,fp2);  
---------------------
我刚开始时就是像上面一样分开写的(当然源代码复杂的多了),后来感觉上面的两段代码只是一个参数不同,完全可以做一个函数独立出来,到谁用到的时候再调用需要的参数。这样一来就省掉了一大堆重复的代码。
为了测试,我专门拿了一个300   MB的文件做实验。
谁知就发现了一个大问题,原来分割文件的时候cpu最多用到20%,也只是瞬间而已。而用调用函数的方法分割文件时则狂占cpu,在分割过程中cpu一直在80%以上。
百思不得其解,上网搜了一下,也不知从何下手。
难道调用一个函数要付出这么大代价?以后编程时是不是要一大堆一大堆写几乎重复的代码。
因此发到这里和大家讨论讨论。请各位朋友发表高见。
(PS:程序运行没有问题,分割文件完全正确。)

[解决办法]
贴全代码。
并且,用了优化编译没有?
[解决办法]
我觉得这一句有问题:
s[sizeof(s)]= '\0 ';

1. 不管s是多大,它肯定越界了,注意s最后一个字节是s[sizeof(s)-1]. btw, 很不赞成在这里使用sizeof()
2. 如果作成函数调用的话,每次读的长度是变化的,但sizeof()的结果是个常数(实际上编译时就已决定了).
[解决办法]
函数调用的开销当然大,这是公认的。至于大到多少,没有量化的标准。
函数调用要将多个寄存器入栈,还有可能造成指令预取缓冲无法命中,整个CPU流水线清空,而且还要空循环几个指令周期,等待从内存中读取下一条指令。
[解决办法]
楼上说的不错,sizeof(s)=4,下面这段代码,三个字符一组,一直靠循环连续不断写入文件

for(int i=1;i <=int(temp);i++) //这里同样要考虑最后一次从源文件取的数据块大小
{
fread(s,1,sizeof(s)-1,fp1); /*在块,亦即 sizeof(s)-1 bytes */
s[sizeof(s)-1]= '\0 '; //数组最后一定加结束符 '\0 '
fwrite(s,1,sizeof(s)+1,fp2);
s[0]= '\0 '; //复制完一块数据后把数组s清空,继续复制
}

热点排行