全部博文(842)
分类: 系统运维
2012-05-14 17:16:03
使用上节讨论的函数,我们会知道标准I/O系统的效率。下面的程序和3.9节的程序相似:它使用getc和putc简单地把标准输入拷贝到标准输出。这两个函数可以作为宏实现:
最后,我们有一个读写行的版本:
使用标准I/O函数的耗时结果 |
||||
函数 | 用户CPU(秒) | 系统CPU(秒) | 时钟时间(秒) | 程序代码的字节 |
3.9节里最好的时间 | 0.01 | 0.18 | 6.67 | |
fgets, fputs | 2.59 | 0.19 | 7.15 | 139 |
getc, putc | 10.84 | 0.27 | 12.07 | 120 |
fgetc, fputc | 10.44 | 0.27 | 11.42 | 120 |
3.9节里的单一字节时间 | 124.89 | 161.65 | 288.64 |
对这三个标准I/O版本的每个,用户CPU时间都比3.9节最好的读版本要长,因为一次一字符标准I/O版本有一个执行了1亿次的循环,而一次一行版本的
循环执行了3,14,984次。在read版本里,它循环只执行了12,611次(当缓冲尺寸为8,192时)。在时钟时间里的区别在于用户时间的区别,
以及等待I/O完成所花时间的区别,而系统系统是可比的。
系统时间和之前的大致相同,这是因为内核请求的数量大致相同。注意使用标准I/O函数的优点是我们不用担心缓冲以及选择优化的I/O尺寸。虽然我们必须决定使用fgets的版本的最大行尺寸,但是这比选择优化的I/O尺寸简单。
使用一次一行I/O的版本比使用一次一字符的版本快了近一倍。如果fgets和fputs函数用getc和putc来实现的话,那我们会期望耗时与
getc版本相似。事实上,我们可能会预期一次一行版本花的时间更长,因为我们在已有的600万次的基础上,加上了额外的200万次函数调用。这个例子里
发生的是一次一行函数使用memccpy函数实现。通常,memccpy函数由汇编而非C实现,为了效率。
最后一个关于这些耗时的有趣的事是fgtc版本比BUFFSIZE=1的3.9节版本快了如此之多。两者都调用了相同数量的函数--大约2亿--然而
fgetc版本在CUP时间上快了近12倍而在时钟时间上稍超出25倍。区别在于使用read的这个版本执行2亿次函数调用,从而造成2亿次系统调用。
fgetc版本里,我们执行了2亿次函数调用,但只有25,222次系统调用。系统调用通常比普通函数调用耗时得多。