我正在使用低级I / O函数'write'在我的代码中将一些数据写入磁盘(Linux上的C语言)。首先,我将数据累积在内存缓冲区中,然后在缓冲区已满时使用“write”将数据写入磁盘。那么'write'的最佳缓冲区大小是多少?根据我的测试,它不是越大越快,所以我在这里寻找答案。
答案 0 :(得分:3)
您希望它是CPU页面大小的倍数,以便尽可能高效地使用内存。
但理想情况下,您希望使用mmap,这样您就不必自己处理缓冲区。
答案 1 :(得分:3)
您可以使用BUFSIZ
<stdio.h>
否则,请使用页面大小sysconf(_SC_PAGESIZE)
的小倍数(例如,该值的两倍)。大多数Linux系统都有4K字节页面(通常与文件系统块大小相同或是文件系统块大小的一小部分)。
正如其他人回答的那样,使用mmap(2)系统调用可能有所帮助。 GNU系统(例如Linux)有一个扩展名:fopen的第二个模式字符串可能包含后者m
,当发生这种情况时,GNU libc会尝试mmap
。
如果您处理的数据几乎与RAM(或其中一半)一样大,您可能还希望使用madvise(2)来微调mmap
的效果。
另请参阅this answer与您的问题非常相似的问题。 (您可以使用64K字节作为合理的缓冲区大小)。
答案 2 :(得分:3)
执行文件系统块大小的倍数的写入可能有一些优势,特别是在您正在更新文件时。如果您将少于部分块写入文件,则操作系统必须读取旧块,合并新内容然后将其写出。如果您按顺序快速写入小块,则不一定会发生这种情况,因为更新将在内存中的缓冲区中完成,这些缓冲区将在以后刷新。尽管如此,如果你没有在每个写入操作中填充一个块(以及正确对齐的块:块大小的倍数,块大小的倍数),那么偶尔会触发一些低效率。
这个传输大小问题不一定会消失。如果您映射文件,然后将memcpy
某些数据映射到地图中,则会使页面变脏。该页面必须在稍后的某个时间刷新:它是不确定的。如果你创建另一个触及同一页面的memcpy
,那么该页面现在可能是干净的,而你又将它弄脏了。所以它写了两次。页面大小的页面对齐副本将是最佳选择。
答案 3 :(得分:2)
“最佳”大小在很大程度上取决于底层文件系统。
stat
和fstat
来电填写数据结构struct stat
,其中包含以下字段:
blksize_t st_blksize; /* blocksize for file system I/O */
操作系统负责为write()块填充此字段的“大小”。但是,使用“良好对齐”的内存(例如,malloc
调用的结果)调用write()也很重要。实现此目标的最简单方法是使用提供的<stdio.h>
流接口(带有FILE *
个对象)。
在许多情况下,使用mmap
和其他答案一样,也可以非常快。请注意,它不适合某些类型的流(例如,套接字和管道)。
答案 4 :(得分:1)
取决于RAM,VM等的数量以及正在写入的数据量。更一般的答案是对哪些缓冲区最适合您正在处理的负载进行基准测试,并使用最有效的方法。