宣布 tokio-uring:Tokio 的 io-uring 支持
今天,我们发布了 “tokio-uring” crate的第一个版本,为Linux上的 io-uring
系统API提供支持。这个版本提供了异步文件操作,我们将在后续版本中增加对更多操作的支持。
要使用 tokio-uring
,首先要在 crate 上添加一个依赖项:
tokio-uring = "0.1.0"
然后,启动 tokio-uring
运行时 ,并从文件中读取:
use tokio_uring::fs::File;
fn main() -> Result<(), Box<dyn std::error::Error>> {
tokio_uring::start(async {
// Open a file
let file = File::open("hello.txt").await?;
let buf = vec![0; 4096];
// Read some data, the buffer is passed by ownership and
// submitted to the kernel. When the operation completes,
// we get the buffer back.
let (res, buf) = file.read_at(buf, 0).await;
let n = res?;
// Display the contents
println!("{:?}", &buf[..n]);
Ok(())
})
}
tokio-uring
运行时在底下使用Tokio运行时,所以它与Tokio类型和库(如hyper和tonic)兼容。下面是和上面一样的例子,但我们不是写到STDOUT,而是写到一个Tokio TCP套接字。
use tokio::io::AsyncWriteExt;
use tokio::net::TcpListener;
use tokio_uring::fs::File;
fn main() {
tokio_uring::start(async {
// Start a TCP listener
let listener = TcpListener::bind("0.0.0.0:8080").await.unwrap();
// Accept new sockets
loop {
let (mut socket, _) = listener.accept().await.unwrap();
// Spawn a task to send the file back to the socket
tokio_uring::spawn(async move {
// Open the file without blocking
let file = File::open("hello.txt").await.unwrap();
let mut buf = vec![0; 16 * 1_024];
// Track the current position in the file;
let mut pos = 0;
loop {
// Read a chunk
let (res, b) = file.read_at(buf, pos).await;
let n = res.unwrap();
if n == 0 {
break;
}
socket.write_all(&b[..n]).await.unwrap();
pos += n as u64;
buf = b;
}
});
}
});
}
所有的 tokio-uring
操作都是真正的异步,与 tokio::fs
提供的API不同,后者在线程池上运行。从线程池中使用同步的文件系统操作会增加大量的开销。有了io-uring
,我们可以在同一个线程中异步地执行网络和文件系统操作。但是,io-uring
的内容很多。
Tokio目前的Linux实现使用非阻塞系统调用和 epoll
来进行事件通知。使用 epoll
,一个经过调整的TCP代理将花费70%到80%的CPU周期在用户空间之外,包括执行系统调用和在内核和用户空间之间复制数据的周期。Io-uring
通过消除大多数系统调用来减少开销,对于某些操作,提前映射用于字节缓冲区的内存区域。早期将 io-uring
与 epoll
进行比较的基准是有希望的;用C语言实现的TCP echo客户端和服务器显示了高达60%的改进。
最初的 tokio-uring
版本提供了一套适度的API,但我们计划在未来的版本中增加对 io-uring
的所有功能的支持。请看设计文件以了解我们的发展方向。
所以,请尝试一下这个 crate,并随时提出问题或报告问题。
另外,我们要感谢所有在这一过程中提供帮助的人,特别是Glauber Costa(Glommio的作者),他耐心地回答了我的许多问题,withoutboats最初的探索(Ringbahn)和花时间与我讨论设计问题,以及 quininer
在纯Rust `io-uring 绑定上的出色工作。