Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1426324
  • 博文数量: 842
  • 博客积分: 12411
  • 博客等级: 上将
  • 技术积分: 5772
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-14 14:43
文章分类

全部博文(842)

文章存档

2013年(157)

2012年(685)

分类: 系统运维

2012-05-14 17:16:03



使用上节讨论的函数,我们会知道标准I/O系统的效率。下面的程序和3.9节的程序相似:它使用getc和putc简单地把标准输入拷贝到标准输出。这两个函数可以作为宏实现: 


  1. #include <stdio.h>

  2. int main(void)
  3. {
  4.     int c;
  5.     while ((c = getc(stdin)) != EOF)
  6.         if (putc(c, stdout) == EOF)
  7.             exit(1);
  8.     if (ferror(stdin))
  9.         exit(1);
  10.     exit(0);
  11. }



我们可以使用fgetc和fputc实现这个程序的另一个版本,它们应该是函数,而不是宏。(这里我们不展示这种小的改变。)

最后,我们有一个读写行的版本:


  1. #include <stdio.h>

  2. #define MAXLINE 4096

  3. int
  4. main(void)
  5. {
  6.     char buf[MAXLINE];

  7.     while (fgets(buf, MAXLINE, stdin) != NULL)
  8.         if (fputs(buf, stdout) == EOF)
  9.             exit(1);

  10.     if (ferror(stdin))
  11.         exit(1);

  12.     exit(0);
  13. }



注意上面两个程序里,我们没有显式地关闭标准I/O流。相反,我们知道exit函数会冲洗任何没有写的数据然后关闭所有打开的流。(我们将在8.5节讨论 这个。)有趣的是比较这三个程序的耗时与3.9节的耗时。我们在下表展示操作同一个文件(98.5M,300万行)的数据:
使用标准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次系统调用。系统调用通常比普通函数调用耗时得多。


作为一个反对者,你应该已经注意到这些耗时结果只在它们运行的单一系统上有效。这个结果取决于在每个UNIX系统上都不一样的许多实现的特性。尽管如此, 有这些类似的数字,并解释这些版本为什么不同,帮助我们更好地了解这个系统。

从这节和3.9节,我们已经知道了标准I/O库并不比直接调用read和 write慢很多。我们看到的大概的花销是大约0.11秒的时钟时间用getc和putc来拷贝一M的数据。对于多数的实际的程序,用户CPU时间最多被 程序花费掉,而不是标准I/O函数。
阅读(330) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~