mill-io 1.0.1

A lightweight event loop library for Rust that provides efficient non-blocking I/O management without relying on heavyweight async runtimes.
Documentation

Mill-IO

A lightweight, production-ready event loop library for Rust that provides efficient non-blocking I/O management without relying on heavyweight async runtimes. Mill-IO is a reactor-based event loop implementation built on top of mio that offers:

  • Runtime-agnostic: No dependency on Tokio or other async runtimes
  • Cross-platform: Leverages mio's polling abstraction (epoll, kqueue, IOCP)
  • Thread pool integration: Configurable worker threads for handling I/O events
  • Object pooling: Reduces allocation overhead for frequent operations
  • Clean API: Simple registration and handler interface

Installation

Add Mill-IO to your Cargo.toml:

[dependencies]
mill-io = "1.0.1"

For unstable features:

[dependencies]
mill-io = { version = "1.0.1", features = ["unstable"] }

Core Components

  • Polling Abstraction: Cross-platform event notification using mio
  • Reactor Core: Manages event loop lifecycle and dispatches events
  • Thread Pool: Scalable task execution with work distribution
  • Object Pool: Memory-efficient buffer management
  • Handler Registry: Thread-safe event handler management

Quick Start

use mill_io::{EventLoop, EventHandler};
use mio::{net::TcpListener, Interest, Token};

struct EchoHandler;

impl EventHandler for EchoHandler {
    fn handle_event(&self, event: &mio::event::Event) {
        // Handle incoming connections
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut event_loop = EventLoop::default();
    let mut listener = TcpListener::bind("127.0.0.1:8080")?;
    
    event_loop.register(
        &mut listener,
        Token(1),
        Interest::READABLE,
        EchoHandler
    )?;
    
    println!("Server listening on 127.0.0.1:8080");
    event_loop.run()?;
    
    Ok(())
}

See examples/echo_server.rs for a complete implementation.

Examples

Mill-IO includes several practical examples demonstrating different use cases:

  • Echo Server (examples/echo_server.rs): Basic TCP echo server implementation
  • HTTP Server (examples/http_server.rs): Simple HTTP server handling GET requests
  • File Watcher (examples/file_watcher.rs): File system monitoring with inotify
  • JSON-RPC Server (examples/jsonrpc-server.rs): JSON-RPC 2.0 server implementation

Run an example:

cargo run --example echo_server

Configuration

Mill-IO provides flexible configuration options:

Default Configuration

use mill_io::EventLoop;

// Uses 4 worker threads, 1024 event capacity, 100ms timeout
let event_loop = EventLoop::default();

Custom Configuration

use mill_io::EventLoop;

let event_loop = EventLoop::new(
    8,      // Number of worker threads
    2048,   // Maximum events per poll iteration
    50      // Poll timeout in milliseconds
)?;

Thread Pool Sizing Guidelines

  • CPU-bound tasks: Number of CPU cores
  • I/O-bound tasks: 2-4x number of CPU cores
  • Mixed workloads: Start with CPU cores + 2

Memory Usage

Object pooling reduces memory allocations. Pool sizes are automatically managed but can be tuned based on workload patterns.

Why It Exists

Mill-IO was created to address the need for efficient I/O management in applications that want to avoid the complexity and overhead of full async runtimes. Specifically designed for projects like Coinswap that require:

  • Fine-grained control over concurrency
  • Minimal runtime dependencies
  • Predictable performance characteristics
  • Runtime-agnostic architecture

Rather than forcing applications into a specific async ecosystem, Mill-IO provides the building blocks for custom I/O handling while maintaining simplicity and performance.

Features

  • Cross-platform I/O polling
  • Configurable thread pool
  • Object pooling for buffers
  • Thread-safe handler registry
  • Graceful shutdown handling
  • Timer wheel implementation (planned)
  • Rate limiting support (planned)
  • Connection pooling (planned)

Architecture

Mill-IO follows a modular, reactor-based architecture for efficient I/O event handling:

EventLoop
    |
    +-- Reactor
        |
        +-- PollHandle (Cross-platform polling)
        |   |
        |   +-- Handler Registry (Token -> Handler mapping)
        |   |
        |   +-- mio::Poll (System polling interface)
        |
        +-- ThreadPool (Worker threads)
            |
            +-- Worker threads (Configurable count)
            |
            +-- Job queue (Event dispatching)

Core Components

  1. Reactor Core

    • Central event loop coordinator
    • Event polling and dispatch management
    • Configurable timeouts and capacity
    • Graceful shutdown handling
  2. Handler Registry

    • Lock-free token-to-handler mapping
    • O(1) handler lookups
    • Thread-safe registration/deregistration
  3. Thread Pool

    • Configurable worker thread count
    • Work stealing via shared channel
    • Automatic task distribution
    • Support for both MPSC/MPMC channels
  4. Object Pool

    • Efficient buffer recycling
    • Reduced allocation overhead
    • Automatic sizing and cleanup
    • Thread-safe object lifecycle

Key Features

  • Zero-copy I/O: Efficient buffer management via object pooling
  • Cross-platform: Unified API across epoll/kqueue/IOCP
  • Lock-free: Minimal contention in hot paths
  • Predictable: Direct control over I/O operations

For detailed architectural documentation, see Architecture Guide

Platform Support

Mill-IO supports all major platforms through mio:

  • Linux: epoll-based polling
  • macOS: kqueue-based polling
  • Windows: IOCP-based polling
  • FreeBSD/OpenBSD: kqueue-based polling

Minimum supported Rust version: 1.70

License

Licensed under the Apache License, Version 2.0. See LICENSE for details.

Contributing

Contributions are welcome! Please read our Contributing Guide for details on our development process, coding standards, and how to submit pull requests.

For questions or discussions, feel free to open an issue or reach out to the maintainers.