我想提高将几个通常很小的文件写入网络附加卷的软件的吞吐量。
该卷限制为100 IOPS和80 MB / s的带宽。
此刻我达到了100 IOPS,但带宽与可达到的80 MB / s距离非常远,约4 MB / s,甚至更低。
我相信主要的问题是我们提出了许多小请求,这些小请求使IOPS饱和,但是带宽几乎未被利用。
该软件是用C语言编写的,我几乎可以控制一切,直到实际的write
系统调用为止。
目前,该体系结构是多线程的,其中多个线程充当“假脱机程序”并进行同步write
调用,每个线程用于一个不同的文件。
因此,假设我们有文件a
,b
和c
以及线程t1
,t2
和t3
。
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块(5/10 KB)。
我认为解决此问题的唯一方法是发出更大的请求,但是每个文件都很小,因此我不确定什么是最好的转发方式。
一个可能的想法可能是发出一个write
请求,而不是几个请求的循环,因此查找文件有多大,分配足够的内存,填充缓冲区并最终执行一个{{1} }。
另一个想法可能是切换异步io,但是我不了解这种情况下的优势。
您还有其他建议吗?
答案 0 :(得分:1)
您可以将所有文件放入内存中的tar归档文件中。然后,您可以将tar存档作为一个大请求写入,然后将tar存档解压缩为一个单独的过程,从而释放编写程序。
这是一个更具创意的想法。首先,根据文件的保存位置(可能是目录)将文件分组。然后在组中找到最大的文件。填充其他文件的内容,以使每个文件的大小相同。然后将文件彼此追加,这样便有了一个大文件。发送该写请求。因此,现在我们编写了一个大文件,其中包含许多大小相等的较小文件。因此,请使用linux split命令将文件拆分为多个原始文件(https://kb.iu.edu/d/afar)。这可能有效,但是您必须在文件末尾添加空白。
编辑:必须注意,这些解决方案不可扩展。长期的解决方案将是@AndrewHenle在评论中建议的。