分类: 系统运维
2012-03-28 12:55:02
下面的代码只使用read和write函数复制一个文件。
4、这个例子对于文本文件和字节文件都可以工作,因为对于UNIX内核两者没有任何区别。
我们仍有一个没有回答的问题:我们如何来选取BUFFSIZE的值?在回答这个问题之前,让我们用不同的BUFFSIZE值来运行下这个程序。我们使用上
面的程序,把标准输出重定向到/dev/null。测试使用使用4,096字节的块的Linux
ext2文件系统。下表显示了用20个不同的buffer值读取一个103,316,352字节的文件的结果:
在Linux上使用不同的buffer大小读取文件的结果 |
||||
BUFFSIZE |
用户CUP(秒数) |
系统CPU(秒数) |
时钟时间(秒数) |
循环数 |
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.18 | 0.23 | 7.84 | 100,894 |
2,048 | 0.05 | 0.19 | 6.82 | 50,447 |
4,906 | 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 |
可以看到当BUFFSIZE为4,096时,有一个最小的系统时间,超过这个大小的buffer没有更好的效果。
多数文件系统支持某种超前读入的方法来提高性能。当发现有一连串的读操作时,系统尝试读入比系统请求更多的数据,假设程序会在不久后读到它们。从上表中最后几行可以看到,在超过128K后ext2的超前读入就不再有效果了。
我们待会再回来讨论这个时间例子。在3.14节我们会展示同步写的效果;在5.8节我们会比较这些未缓冲I/O时间和标准I/O库。
当尝试测量读写文件的程序的性能时要注意,操作系统会尝试把文件缓存到主内存(incore,意思为main
memory,过去系统主内存是用铁核--ferrite core做成的,这也是术语“core
dump”的由来:一个程序的主内存映象存储到磁盘上的一个文件用来诊断),所以当你重复地测量这个程序的性能时,后面的时间会比第一次要少。这时因为第
一次运行会导致文件被缓存到系统缓存中,而后续运行会从系统缓存而不是硬盘里访问文件。
在上表中的测试里,每次不同buffer尺寸的运行都是使用文件的不同拷贝,这样当前运行就不会找到上次运行的缓存数据。这些文件都已经有足够大,没有全部留在缓存中。(测试系统的配置是512M的RAM)。