Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
306 changes: 306 additions & 0 deletions USAGE_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,306 @@
# rio Usage Guide

## Introduction

rio is a pure Rust io_uring library built on libc, thread & async friendly, and misuse resistant.

## Quick Start

### Basic File Read

```rust
use rio::{Rio, Uring};

fn main() -> std::io::Result<()> {
let uring = Uring::new(32)?;
let rio = Rio::new(uring)?;

let file = rio.open_at(
rio.cwd()?,
"example.txt",
rio::OpenOptions::new().read(true),
)?;

let buf = vec![0u8; 4096];
let (file, result) = file.read_at(buf, 0).wait()?;

println!("Read {} bytes", result?);
Ok(())
}
```

### Async File Write

```rust
use rio::{Rio, Uring};
use std::io::Write;

#[tokio::main]
async fn main() -> std::io::Result<()> {
let uring = Uring::new(32)?;
let rio = Rio::new(uring)?;

let file = rio.open_at(
rio.cwd()?,
"output.txt",
rio::OpenOptions::new()
.write(true)
.create(true)
.truncate(true),
)?;

let data = b"Hello, io_uring!";
let buf = data.to_vec();
let (_file, result) = file.write_at(buf, 0).await?;

println!("Wrote {} bytes", result?);
Ok(())
}
```

## Advanced Usage

### Parallel Operations

```rust
use rio::{Rio, Uring};
use std::sync::Arc;

fn parallel_reads() -> std::io::Result<()> {
let uring = Uring::new(64)?;
let rio = Arc::new(Rio::new(uring)?);

let mut handles = vec![];

for i in 0..4 {
let rio = Arc::clone(&rio);
handles.push(std::thread::spawn(move || {
let file = rio.open_at(
rio.cwd().unwrap(),
format!("file_{}.txt", i),
rio::OpenOptions::new().read(true),
).unwrap();

let buf = vec![0u8; 1024];
let (_file, result) = file.read_at(buf, 0).wait().unwrap();
result.unwrap()
}));
}

for handle in handles {
let bytes = handle.join().unwrap();
println!("Thread read {} bytes", bytes);
}

Ok(())
}
```

### Network Operations

```rust
use rio::{Rio, Uring, TcpListener};
use std::net::SocketAddr;

fn tcp_server() -> std::io::Result<()> {
let uring = Uring::new(32)?;
let rio = Rio::new(uring)?;

let addr: SocketAddr = "127.0.0.1:8080".parse()?;
let listener = TcpListener::bind(&rio, addr)?;

println!("Listening on {}", addr);

loop {
let (stream, addr) = listener.accept().wait()?;
println!("Connection from {}", addr);

// Handle connection in new thread
std::thread::spawn(move || {
// Handle stream...
});
}
}
```

### Buffer Management

```rust
use rio::{Rio, Uring};

// rio automatically manages buffer lifetimes
fn safe_buffer_usage() -> std::io::Result<()> {
let uring = Uring::new(32)?;
let rio = Rio::new(uring)?;

let file = rio.open_at(
rio.cwd()?,
"data.bin",
rio::OpenOptions::new().read(true),
)?;

// Buffer is automatically managed
// No manual memory management needed
let buf = vec![0u8; 8192];
let (_file, bytes_read) = file.read_at(buf, 0).wait()?;

println!("Read {} bytes safely", bytes_read?);
Ok(())
}
```

## Performance Tips

### Queue Depth Tuning

```rust
// Larger queue depth for more parallelism
let uring = Uring::new(256)?; // Default: 32

// Smaller for lower latency
let uring = Uring::new(16)?;
```

### Batch Operations

```rust
use rio::{Rio, Uring};

fn batch_writes() -> std::io::Result<()> {
let uring = Uring::new(64)?;
let rio = Rio::new(uring)?;

let file = rio.open_at(
rio.cwd()?,
"batch.txt",
rio::OpenOptions::new().write(true).create(true),
)?;

// Submit multiple writes
let mut completions = vec![];
for i in 0..10 {
let data = format!("Line {}\n", i).into_bytes();
let offset = (i * 10) as u64;
completions.push(file.write_at(data, offset));
}

// Wait for all completions
for completion in completions {
let (_file, result) = completion.wait()?;
println!("Wrote: {} bytes", result?);
}

Ok(())
}
```

## Troubleshooting

### Permission Denied

```bash
# io_uring requires kernel 5.1+
uname -r

# Check io_uring support
cat /proc/sys/kernel/io_uring_disabled
# Should be 0 (enabled)
```

### Resource Limits

```rust
// Increase max entries if needed
let uring = Uring::new(512)?;

// Check system limits
cat /proc/sys/fs/aio-max-nr
```

### Debug Mode

```rust
// Enable debug logging
std::env::set_var("RIO_DEBUG", "1");

// Use Rio with debug output
let uring = Uring::new(32)?;
let rio = Rio::new(uring)?;
```

## Common Patterns

### Read-Modify-Write

```rust
use rio::{Rio, Uring};

fn read_modify_write() -> std::io::Result<()> {
let uring = Uring::new(32)?;
let rio = Rio::new(uring)?;

let file = rio.open_at(
rio.cwd()?,
"data.txt",
rio::OpenOptions::new().read(true).write(true),
)?;

// Read
let buf = vec![0u8; 1024];
let (file, bytes_read) = file.read_at(buf, 0).wait()?;

// Modify
let mut data = String::from_utf8_lossy(&bytes_read).to_string();
data.push_str("\nNew content");

// Write back
let (_file, _bytes_written) = file.write_at(data.into_bytes(), 0).wait()?;

Ok(())
}
```

### Streaming Large Files

```rust
use rio::{Rio, Uring};

fn stream_large_file() -> std::io::Result<()> {
let uring = Uring::new(32)?;
let rio = Rio::new(uring)?;

let file = rio.open_at(
rio.cwd()?,
"large_file.bin",
rio::OpenOptions::new().read(true),
)?;

let mut offset = 0u64;
let chunk_size = 4096u64;

loop {
let buf = vec![0u8; chunk_size as usize];
let (f, bytes_read) = file.read_at(buf, offset).wait()?;

if bytes_read? == 0 {
break; // EOF
}

// Process chunk...
offset += chunk_size;
}

Ok(())
}
```

## Community

- **Repository**: https://github.com/spacejam/rio
- **Documentation**: https://docs.rs/rio
- **Chat**: https://discord.gg/Z6VsXds
- **Sponsor**: https://github.com/sponsors/spacejam

---

*Community contribution - unofficial usage guide*