What you need
Rust 1.99 or later. Nuclei is written in the 2024 edition; your crate may use any edition. Each system runs on its own kernel interface:
| System | Backend |
|---|---|
| Linux, Android | io_uring where the kernel (6.1 or later) and the sandbox allow it, else epoll |
| illumos | epoll |
| macOS, iOS, FreeBSD, NetBSD, OpenBSD, DragonFly | kqueue |
| Windows | I/O completion ports |
Add it
cargo add nucleior in Cargo.toml:
[dependencies]
nuclei = "0.5"Nothing else is needed: the read and write helpers, the stream traits and the macros all come with the crate.
A first program
#[nuclei::main]
async fn main() {
let answer = nuclei::spawn(async { 6 * 7 }).await;
println!("the answer is {answer}");
}the answer is 42#[nuclei::main] runs the async main on the runtime, and nuclei::spawn places a task on one of its shards; awaiting the task gives its output. There is nothing to configure: the first spawn or block_on starts the default runtime, with one worker per core the process may run on.
Features
| Feature | Default | What it gives |
|---|---|---|
epoll | on | Names epoll beside iouring. Epoll is built on Linux either way. |
iouring | on | The io_uring driver, on Linux and Android. Without it those systems run on epoll. |
attributes | on | #[nuclei::main], #[nuclei::test] and #[nuclei::bench]. |
recycle | off | Node memory of the lock-free queues, maps and channels underneath, from a per-thread cache instead of the global allocator. |
io-stats | off | Each worker's IO in stats: counts of its operations and bytes, and IO latencies when recorded (Production). Off by default; without it no IO path carries counting or timing code. |
recycle is for applications: cargo turns a feature on for every user of a crate in a build, so a library that enabled it would enable it for all of them.
[dependencies]
# Linux on epoll only, keeping the attribute macros:
nuclei = { version = "0.5", default-features = false, features = ["attributes"] }Which backend runs
fn main() {
nuclei::block_on(async {
println!("IO runs on {:?}", nuclei::Proactor::backend());
});
}With nothing set, Nuclei takes io_uring where the kernel lets the process have the rings its shards use, and the platform's poller otherwise. The probe is safe, even under a seccomp filter that kills a process for calling io_uring_setup. NUCLEI_BACKEND picks one by hand: auto, io_uring or epoll on Linux, kqueue on macOS and the BSDs, iocp on Windows.
NUCLEI_BACKEND=epoll cargo runA backend named by hand that the process cannot have is an error with the reason, never a silent fallback. Backends has the details, Errors the messages.