我想解释一下第二张图表中峰值的原因是什么。
事实上,使用的虚函数std::ofstream
会导致性能下降,类似于我们在第一张图片上看到的情况,但它没有给出为什么当手动缓冲区大小小于 1024 字节时性能最高的原因。
这个问题涉及到系统调用和内部类的内部writev()
实现的高成本。write()
std::filebuf
std::ofstream
为了展示如何write()
影响性能,我在我的 Linux 机器上使用该工具进行了一个简单的测试,dd
以复制具有不同缓冲区大小(bs
选项)的 10MB 文件:
test@test$ time dd if=/dev/zero of=zero bs=256 count=40000
40000+0 records in
40000+0 records out
10240000 bytes (10 MB) copied, 2.36589 s, 4.3 MB/s
real 0m2.370s
user 0m0.000s
sys 0m0.952s
test$test: time dd if=/dev/zero of=zero bs=512 count=20000
20000+0 records in
20000+0 records out
10240000 bytes (10 MB) copied, 1.31708 s, 7.8 MB/s
real 0m1.324s
user 0m0.000s
sys 0m0.476s
test@test: time dd if=/dev/zero of=zero bs=1024 count=10000
10000+0 records in
10000+0 records out
10240000 bytes (10 MB) copied, 0.792634 s, 12.9 MB/s
real 0m0.798s
user 0m0.008s
sys 0m0.236s
test@test: time dd if=/dev/zero of=zero bs=4096 count=2500
2500+0 records in
2500+0 records out
10240000 bytes (10 MB) copied, 0.274074 s, 37.4 MB/s
real 0m0.293s
user 0m0.000s
sys 0m0.064s
如您所见:缓冲区越小,写入速度越低,因此dd
在系统空间中花费的时间越多。因此,当缓冲区大小减小时,读/写速度会降低。
但是为什么在主题创建者手动缓冲测试中手动缓冲大小小于 1024 字节时速度会达到峰值?为什么它几乎是恒定的?
解释与std::ofstream
实现有关,尤其是与std::basic_filebuf
.
默认情况下,它使用 1024 字节缓冲区(BUFSIZ 变量)。因此,当您使用小于 1024 的片段写入数据时,writev()
(不是write()
)系统调用至少会为两个ofstream::write()
操作调用一次(片段的大小为 1023 < 1024 - 第一个写入缓冲区,第二个强制写入第一个和第二)。基于此,我们可以得出结论,ofstream::write()
速度不依赖于峰值之前的手动缓冲区大小(write()
很少调用至少两次)。
ofstream::write()
当您尝试使用call一次写入大于或等于 1024 字节的缓冲区时,writev()
系统调用会为每个ofstream::write
. 因此,您会看到当手动缓冲区大于 1024(峰值之后)时速度会增加。
此外,如果您想设置std::ofstream
缓冲区大于 1024 缓冲区(例如,8192 字节缓冲区)使用streambuf::pubsetbuf()
并调用ostream::write()
以使用 1024 大小的块写入数据,您会惊讶于写入速度将与使用相同1024 缓冲区。这是因为- 内部类 - 的实现std::basic_filebuf
std::ofstream
是硬编码的,以在传递的缓冲区大于或等于 1024 字节时强制writev()
为每个调用调用系统调用(参见basic_filebuf::xsputn()源代码)。在2014-11-05报告的 GCC bugzilla 中还有一个未解决的问题。ofstream::write()
因此,可以使用两种可能的情况来解决这个问题:
- 替换
std::filebuf
为您自己的班级并重新定义std::ofstream
- 将必须传递给 的缓冲区
ofstream::write()
划分为小于 1024 的块,并ofstream::write()
逐个传递给
- 不要将小块数据传递给
ofstream::write()
以避免降低虚拟功能的性能std::ofstream