c - 提高在 C 中写入大量小文件的吞吐量

标签 c linux io filesystems

我想提高将几个通常很小的文件写入网络附加卷的软件的吞吐量。

卷限制为 100 IOPS 和 80 MB/s 的带宽。

目前我已达到 100 IOPS 的饱和,但带宽与可达到的 80 MB/s 相去甚远,约为 4 MB/s,甚至更少。

我认为主要问题是我们提出了很多小请求,这些小请求使 IOPS 饱和,但带宽几乎没有得到利用。

该软件是用 C 语言编写的,我几乎可以控制一切,包括实际的write 系统调用。

目前架构是多线程的,多个线程作为“后台处理程序”工作并进行同步 write 调用,每个线程针对不同的文件。

假设我们有文件 abc 以及线程 t1t2t3

t1 将打开 a 并在循环中调用类似 write(fd_a, buff_a, 1024) 的内容,同样会执行 t2 (write(fd_b, buff_b, 1024)) 和t3 (write(fd_c, buff_c, 1024))。

每个文件都是一个新文件,因此它会在第一次写入时创建。

我认为问题在于操作系统发出的请求(在 Linux IO 调度程序合并之后)非常小,每个请求大约为 10/20 block (5/10 千字节)。

我认为解决问题的唯一方法是提出更大的请求,但每个文件都很小,所以我不太确定什么是最好的前进方式。

一个可能的想法是发出单个write请求而不是多个请求的循环,因此查找文件有多大,分配足够的内存,填充缓冲区并最终执行单个

另一个想法可能是切换到 async io,但我不明白在这种情况下会有什么优势。

您还有什么建议吗?

最佳答案

您可以将所有文件放入内存中的 tar 存档中。然后您可以将 tar 存档作为一个大请求写入,然后将 tar 存档作为一个单独的进程解压缩,从而释放写入程序。

这里有一个更“有创意”的idea。首先根据文件的保存位置(可能按目录)将文件分组。然后找到组中最大的文件。填充每个其他文件的内容,使每个文件的大小相同。然后将这些文件相互附加,这样您就有了一个大文件。发送该写入请求。所以现在我们写了一个大文件,其中包含许多大小相同的小文件。所以使用 linux split 命令将文件拆分成多个原始文件(https://kb.iu.edu/d/afar)。这可能有效,但您必须接受在文件末尾进行填充。

编辑:重要的是要注意这些解决方案不可扩展。长期解决方案将是@AndrewHenle 在评论中提出的建议。

关于c - 提高在 C 中写入大量小文件的吞吐量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51898141/

相关文章:

c# - 使用 Windows 资源管理器的重命名事件 Hook 我的程序

c - 仅左移数字的一部分

c - 获取一位用户输入

c - Stack Smashing 尝试给出段错误

c - 防止 gcc 内联函数

c - 解析具有特定关键字匹配的文本文件

Java 在文件中存储 boolean 数组并快速读取

c - 从 libc 中的函数返回的字符串分配在哪里?

linux - 在 gnuplot 中绘制多个图形的脚本

linux - 我如何使用 Bash 切割开始和结束的部分?