#async-io #io-uring #iocp #async #fs #net

completeio

基于完成的 IO 驱动程序和异步运行时

1 个不稳定版本

0.1.0 2023年9月26日

#1353 in 异步

MIT 许可证

240KB
4.5K SLoC

CompleteIo

MIT licensed crates.io docs.rs

基于 IOCP/io_uring/mio 的每个核心的 Rust IO 驱动程序和异步运行时。名称来源于“基于完成的 IO”。

此存储库是 compio 的分支。

为什么不使用 Compio?

项目有不同的目标

  • 提供低开销的 IO 驱动程序,在初始化时预分配内存

  • 驱动程序 API 接受非 'static IO 缓冲区

    • 驱动程序不拥有缓冲区
    • 缓冲区必须为 Unpin
  • 偏向于 IoUring API 以在 Linux 上实现零成本抽象

    • 操作固定大小提交队列
    • 外部运行时可以将尚未排队操作的队列作为单个批次提交
    • 计时器作为 Timeout 操作公开,并使用当可用时具有挂起感知的 CLOCK_BOOTTIME 时钟源
  • 异步运行时是测试驱动程序实现的示例运行时

快速入门

启用 runtime 功能后,我们可以使用高级 API 执行 fs & net IO。

use completeio::{fs::File, task::block_on};

let buffer = block_on(async {
    let file = File::open("Cargo.toml").unwrap();
    let (read, buffer) = file.read_to_end_at(Vec::with_capacity(1024), 0).await;
    let read = read.unwrap();
    assert_eq!(read, buffer.len());
    String::from_utf8(buffer).unwrap()
});
println!("{}", buffer);

同时,您也可以手动控制低级驱动程序

use arrayvec::ArrayVec;
use std::collections::VecDeque;
use completeio::{
    buf::IntoInner,
    driver::{AsRawFd, Driver, Entry, CompleteIo},
    fs::File,
    op::ReadAt,
};

let mut driver = Driver::new().unwrap();
let file = File::open("Cargo.toml").unwrap();
// Attach the `RawFd` to driver first.
driver.attach(file.as_raw_fd()).unwrap();

// Create operation and push it to the driver.
let mut op = ReadAt::new(file.as_raw_fd(), 0, Vec::with_capacity(4096));
let mut ops = VecDeque::from([(&mut op, 0).into()]);
driver.push_queue(&mut ops);

// Poll the driver and wait for IO completed.
let mut entries = ArrayVec::<Entry, 1>::new();
unsafe {
    driver
        .submit_and_wait_completed(None, &mut entries)
        .unwrap();
}
let entry = entries.drain(..).next().unwrap();
assert_eq!(entry.user_data(), 0);

// Resize the buffer by return value.
let n = entry.into_result().unwrap();
let mut buffer = op.into_inner();
unsafe {
    buffer.set_len(n);
}

println!("{}", String::from_utf8(buffer).unwrap());

依赖项

~0.2–13MB
~102K SLoC