Linux 上的缓冲异步文件 I/O [英] buffered asynchronous file I/O on linux

查看:24
本文介绍了Linux 上的缓冲异步文件 I/O的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找在 linux 上进行异步文件 I/O 的最有效方法.

I am looking for the most efficient way to do asynchronous file I/O on linux.

POSIX glibc 实现在用户空间使用线程.

The POSIX glibc implementation uses threads in userland.

原生 aio 内核 api 仅适用于无缓冲操作,内核添加了对缓冲操作的支持的补丁存在,但这些补丁已经超过 3 年了,似乎没有人关心将它们集成到主线中.

The native aio kernel api only works with unbuffered operations, patches for the kernel to add support for buffered operations exist, but those are >3 years old and no one seems to care about integrating them into the mainline.

我发现了许多其他允许异步 I/O 的想法、概念和补丁,尽管其中大部分都出现在 3 年以上的文章中.在今天的内核中,哪些是真正可用的?我读过关于 servlets、acalls、内核线程的东西以及更多我现在不记得的东西.

I found plenty of other ideas, concepts, patches that would allow asynchronous I/O, though most of them in articles that are also >3 years old. What of all this is really available in todays kernel? I've read about servlets, acalls, stuff with kernel threads and more things I don't even remember right now.

在当今内核中进行缓冲异步文件输入/输出的最有效方法是什么?

What is the most efficient way to do buffered asynchronous file input/output in todays kernel?

推荐答案

除非您想编写自己的 IO 线程池,否则 glibc 实现是一个可以接受的解决方案.对于完全在用户空间中运行的东西,它实际上非常有效.

Unless you want to write your own IO thread pool, the glibc implementation is an acceptable solution. It actually works surprisingly well for something that runs entirely in userland.

根据我的经验,内核实现根本不适用于缓冲 IO(尽管我看到其他人说相反的!).如果您想通过 DMA 读取大量数据,这很好,但是如果您打算利用缓冲区缓存,那当然会浪费很多时间.
另请注意,内核 AIO 调用实际上可能会阻塞.有一个有限大小的命令缓冲区,大的读取被分成几个较小的.一旦队列已满,异步命令就会同步运行.惊喜.我在一两年前遇到过这个问题,但找不到解释.四处打听给了我是的,当然,这就是它的工作原理"的答案.
据我所知,尽管多年来似乎有几种可行的解决方案可用,但对支持缓冲 aio 的官方"兴趣也不是特别大.我读过的一些论点是无论如何你都不想使用缓冲区"和没有人需要那个"和大多数人甚至还没有使用 epoll".所以,嗯……嗯.

The kernel implementation does not work with buffered IO at all in my experience (though I've seen other people say the opposite!). Which is fine if you want to read huge amounts of data via DMA, but of course it sucks big time if you plan to take advantage of the buffer cache.
Also note that the kernel AIO calls may actually block. There is a limited size command buffer, and large reads are broken up into several smaller ones. Once the queue is full, asynchronous commands run synchronously. Surprise. I've run into this problem a year or two ago and could not find an explanation. Asking around gave me the "yeah of course, that's how it works" answer.
From what I've understood, the "official" interest in supporting buffered aio is not terribly great either, despite several working solutions seem to be available for years. Some of the arguments that I've read were on the lines of "you don't want to use the buffers anyway" and "nobody needs that" and "most people don't even use epoll yet". So, well... meh.

能够通过已完成的异步操作获得 epoll 信号是另一个问题,直到最近,但与此同时,通过 eventfd 可以很好地工作.

Being able to get an epoll signalled by a completed async operation was another issue until recently, but in the meantime this works really fine via eventfd.

请注意,glibc 实现实际上会在 __aio_enqueue_request 内按需产生 个线程.这可能没什么大不了的,因为生成线程不再那么昂贵,但人们应该意识到这一点.如果您对启动异步操作的理解是立即返回",那么该假设可能不成立,因为它可能会先生成一些线程.

Note that the glibc implementation will actually spawn threads on demand inside __aio_enqueue_request. It is probably no big deal, since spawning threads is not that terribly expensive any more, but one should be aware of it. If your understanding of starting an asynchronous operation is "returns immediately", then that assumption may not be true, because it may be spawning some threads first.

编辑:
作为旁注,在 Windows 下存在与 glibc AIO 实现中的情况非常相似的情况,其中立即返回"假设排队异步操作是不正确的.
如果您要读取的所有数据都在缓冲区缓存中,Windows 将决定改为同步运行请求,因为无论如何它都会立即完成.这是有据可查的,当然听起来也很棒.除非有几兆字节要复制,或者如果另一个线程出现页面错误或同时执行 IO(从而竞争锁),立即"可能是一个令人惊讶的长时间——我已经看到立即"时间为 2-5 毫秒.这在大多数情况下都没有问题,但例如在 16.66 毫秒的帧时间限制下,您可能不想冒随机时间阻塞 5 毫秒的风险.因此,可以从我的渲染线程执行异步 IO 没有问题,因为异步不会阻塞"的幼稚假设是有缺陷的.

EDIT:
As a sidenote, under Windows there exists a very similar situation to the one in the glibc AIO implementation where the "returns immediately" assumption of queuing an asynchronous operation is not true.
If all data that you wanted to read is in the buffer cache, Windows will decide that it will instead run the request synchronously, because it will finish immediately anyway. This is well-documented, and admittedly sounds great, too. Except in case there are a few megabytes to copy or in case another thread has page faults or does IO concurrently (thus competing for the lock) "immediately" can be a surprisingly long time -- I've seen "immediate" times of 2-5 milliseconds. Which is no problem in most situations, but for example under the constraint of a 16.66ms frame time, you probably don't want to risk blocking for 5ms at random times. Thus, the naive assumption of "can do async IO from my render thread no problem, because async doesn't block" is flawed.

这篇关于Linux 上的缓冲异步文件 I/O的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆