分类:
2008-11-04 14:55:19
5.8 standard i/o efficiency
比较一下standard i/o和unbuffered i/o的efficiency,同时在standard i/o中比较getc,fgetc和fgets之间的效率。
首先应该声明的是:
1.Getc, fgetc, fgets它们的输入表面上看是FILE*流,其实就是standard i/o内部的缓冲。大部分时间他们只是从其缓冲中取出字符给你。当缓冲中字符取完时会自动调用unbuffered i/o从物理文件中读取一般是一个block的数据。
2.User cpu time的时间,包括getc,fgetc和fgets这些standard i/o函数所花掉的时间,因为他们是user空间。
3.System cpu time即内核耗时包括standard i/o所调用的read, write从物理文件获取数据所消耗的时间。
由1可知,不管我们用getc, fgetc, fgets,还是直接使用read/write每次以一个最优(如block大小)的大小来读取数据,他们最终调用read/write的次数应该都是差不多的,这是standard i/o自己优化的结果。也就是所在system level所耗费的时间基本上差不多。即从内核缓冲向standard i/o的缓冲复制数据消耗的时间一样。
4.Fgetc,getc和fgets在user level消耗的时间应该是不一样的。也就是他们从standard i/o的缓冲向应用程序的缓冲复制数据消耗的时间不同。因为fgetc,getc是一个一个字符复制,对每个字符都要调用一个getc/fgetc函数。而fgets调用的次数较少。当然,因为fgets并不是将fgetc/get封装了一下,因为如果仅仅是将他们封装以下的话,fgets的效率会更低。Fgets之所以效率高,是因为他在从standard i/o 的buffer向应用的buffer复制数据的时候采用的是memccpy()函数,注意不是memcpy。可以参看man memccpy。他从src向dest复制数据,直到复制了n个字符或者遇到了字符c。我们这里的c就是newline字符。Memccpy据说使用汇编实现的高效的函数。
如下是采用unbuffered i/o的read/write循环读取然后写出的效率随不同的一次性读取数据的大小变化而得到的时间对比图:
Figure 3.5. Timing results for reading with different
buffer sizes on Linux |
||||
BUFFSIZE |
User CPU (seconds) |
System CPU (seconds) |
Clock time (seconds) |
#loops |
1 |
124.89 |
161.65 |
288.64 |
103,316,352 |
2 |
63.10 |
80.96 |
145.81 |
51,658,#176 |
4 |
31.84 |
40.00 |
72.75 |
25,829,088 |
8 |
15.17 |
21.01 |
36.85 |
12,914,544 |
16 |
7.86 |
10.27 |
18.76 |
6,457,272 |
32 |
4.13 |
5.01 |
9.76 |
3,228,636 |
64 |
2.11 |
2.48 |
6.76 |
1,614,318 |
128 |
1.01 |
1.27 |
6.82 |
807,159 |
256 |
0.56 |
0.62 |
6.80 |
403,579 |
512 |
0.27 |
0.41 |
7.03 |
201,789 |
1,024 |
0.17 |
0.23 |
7.84 |
100,894 |
2,048 |
0.05 |
0.19 |
6.82 |
50,447 |
4,096 |
0.03 |
0.16 |
6.86 |
25,223 |
8,192 |
0.01 |
0.18 |
6.67 |
12,611 |
16,384 |
0.02 |
0.18 |
6.87 |
6,305 |
32,768 |
0.00 |
0.16 |
6.70 |
3,152 |
65,536 |
0.02 |
0.19 |
6.92 |
1,576 |
131,072 |
0.00 |
0.16 |
6.84 |
788 |
262,144 |
0.01 |
0.25 |
7.30 |
394 |
524,288 |
0.00 |
0.22 |
7.35 |
198 |
如下是使用standard i/o 的效率图表:
Function |
User CPU (seconds) |
System CPU (seconds) |
Clock time (seconds) |
Bytes of program text |
best time from |
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 |
single byte time from |
124.89 |
161.65 |
288.64 |
|
1.Clock_time与system和user时间的和不相同,是因为clock time是一共完成这些操作的耗时,在底层i/o的时候,等待时间不计入system的时间,而是cpu被别的进程获取了。
2.Standard i/o和best time from figure 3.5的system cpu time差不多相等。因为本身standard i/o 使用缓冲对何时调用unbuffered i/o做了优化
3.它们最大的区别在于user cpu time 的区别。Fgets明显优于getc/fgetc。而且他们都不如采用read/write的best time from figure 3.5。
4.Single byte time from figure 3.5肯定不行了,因为他调用read/write也是以一个字符为单位读取的,这样其system time就耗时较多,而且由于总的循环也较多,在user level耗时也多。