use*_*398 4 linux performance latency aio
我正在寻找有关如何为我在Ubuntu Linux 14.04上运行的应用程序提供高效和高性能异步IO的建议.
我的应用程序处理事务并在磁盘/闪存上创建文件.当应用程序正在进行事务处理时,会创建必须附加到磁盘/闪存上的文件的附加块.应用程序还需要在处理新事务时频繁读取此文件的块.除了还要创建必须附加到此文件的新块之外,每个事务可能还需要从该文件中读取不同的块.有一个传入的事务队列,应用程序可以继续处理队列中的事务,以创建足够深的IO操作管道,以隐藏读取访问的延迟或磁盘或闪存上的写入完成.对于尚未写入磁盘/闪存的块(由先前事务放入写入队列)的读取,应用程序将停止,直到相应的写入完成.
我有一个重要的性能目标 - 应用程序应该产生尽可能低的发布IO操作的延迟.我的应用程序大约需要10微秒来处理每个事务,并准备对磁盘/闪存上的文件发出写入或读取.发出异步读取或写入的额外延迟应尽可能小,以便应用程序可以在每次事务处理时尽可能接近10个usecs,只需要进行文件写入时完成每个事务的处理.
我们正在尝试使用io_submit发出写入和读取请求的实现.我将不胜感激任何有关我们要求的最佳方法的建议或反馈.io_submit会给我们最好的表现以达到我们的目标吗?我应该期望每个写入io_submit的延迟和每个读取io_submit的延迟?
使用我们的实验代码(在2.3 GHz Haswell Macbook Pro,Ubuntu Linux 14.04上运行),我们在扩展输出文件时测量写入io_submit大约50个usecs.这太长了,我们甚至没有接近我们的性能要求.任何帮助我以最小延迟启动写请求的指南都将非常感激.
Ano*_*non 11
Linux AIO是一种黑色艺术,有经验的从业者知道陷阱,但由于某种原因,与某人谈论他们还不知道的陷阱是禁忌.从网络和经验,围绕刮伤我已经拿出了几个例子,其中的Linux的异步I/O 提交可能成为(默默)同步(由此将libaio
进入一个阻塞调用):
io_submit()
"提示"(例如,您提交I/O的方式不符合O_DIRECT
对齐约束,文件系统或特定文件系统的配置不支持O_DIRECT
)并静默执行缓冲I/O,导致上面的情况.O_DIRECT
文档和文档中记录的un(der))以及内核中/sys/block/[disk]/queue/nr_requests
系统全局最大AIO请求数(请参阅/sys/block/[disk]/device/queue_depth
文档).使I/O备份并超过内核队列的大小会导致阻塞.
/sys/block/[disk]/queue/max_sectors_kb
)的I/O,它们将在内核中拆分并继续咀嚼多个请求...上面的列表并非详尽无遗.
未来希望的微光,是拟议的功能,它允许程序通过设置要求更好的行为导致AIO提交失败,EAGAIN是否会继续阻止标志.在撰写本文时,AIO EAGAIN补丁是针对4.13内核提交的.即使这些补丁进入未来的内核,您仍然需要(或更高版本)内核使用该功能,并且b)必须知道它没有覆盖的情况(尽管我注意到有完全独立的补丁正在建议在堆叠的被阻止设备触发阻塞时尝试返回EAGAIN.
参考文献:
/proc/sys/fs/aio-max-nr
阻断/缓慢的情况.io_setup()
io_submit()
如何可以回退到缓冲I/O 而不是没有通话.
RWF_NONBLOCK
压缩文件请求时,BTRFS会对缓冲I/O进行调度.RWF_NONBLOCK
通过缓冲I/O"支持"它(参见第3点).从Linux到"Direct IO"GitHub问题的ZFS上的提交还有进一步的讨论.EAGAIN
分配写入.有关:
希望这篇文章可以帮助某些人(如果有帮助你可以帮助你吗?谢谢!).
我在这里作为提议的Boost.AFIO的作者发言.
首先,Linux的KAIO(io_submit)几乎总是堵,除非O_DIRECT已打开,并且不需要任何程度的分配,如果O_DIRECT是你需要阅读和写作上的4K对齐边界4Kb的倍数,否则将强制设备进行读取-modify写.因此,除非您将应用程序重新架构为O_DIRECT且4Kb对齐i/o友好,否则您将无法获得Linux KAIO.
其次,永远不要在写入期间扩展输出文件,强制扩展分配并可能强制元数据刷新.而是将文件的最大范围分配给某个适当大的值,并保留文件末尾的内部原子计数器.这应该将问题简化为仅限于ext4批量和懒惰的分配 - 更重要的是,你不会强制元数据刷新.这应该意味着ext4上的KAIO大部分时间都是异步的,但不可预测的是会同步,因为它会延迟对期刊的延迟分配.
第三,我可能会接近你的问题的方法是使用原子的append(O_APPEND)没有O_DIRECT也不O_SYNC,所以你要做的就是追加更新内核的页面缓存日益增长文件,该文件是非常快和并发安全.然后,您不时地收集垃圾收集日志文件中的哪些数据是陈旧的,并且可以使用fallocate(FALLOC_FL_PUNCH_HOLE)释放其范围,以便物理存储不会永远增长.这推动了将内存写入合并到内核的问题,其中已经花了很多精力来实现这一点,并且因为它总是向前进行写入,所以你会看到写入按照与它们编写的序列非常接近的顺序命中物理存储.使功率损耗恢复简单明了.后一种选择是数据库如何做到这一点,并且实际上日志文件系统就是这样做的,尽管你可能需要对你的软件进行大量的重新设计,但这种算法已被证明是在通用问题情况下延迟与耐久性的最佳平衡.
如果以上所有内容看起来都很重要,操作系统已经提供了所有这三种技术,这些技术汇总成一个高度调整的实现,更好地称为内存映射:4Kb对齐i/o,O_DIRECT,永不扩展文件,所有异步i/o.在64位系统上,只需将文件重定位到非常大的数量并将其映射到内存中.根据需要进行读写.如果您的i/o模式混淆了可能发生的内核页面算法,那么您可能需要在这里和那里使用madvise()来鼓励更好的行为.madvise()更少,更信任我.
很多人尝试使用各种O_DIRECT算法复制mmaps而没有意识到mmaps已经可以做你需要的一切.我建议首先探讨这些,如果Linux不会尝试FreeBSD,它有一个更可预测的文件i/o模型,只有这样才能深入研究推出自己的i/o解决方案的领域.作为一整天都在做这些事情的人,我强烈建议你尽可能避免使用它们,归档系统是古怪和奇怪行为的恶魔坑.将永无止境的调试留给其他人.