<p align="center">
  <img src="momo.png" alt="Momo Logo" width="250">
</p>

# Momo: High-Performance, Atomic-Free Async Runtime

[![Crates.io](https://img.shields.io/crates/v/momo-rs.svg)](https://crates.io/crates/momo-rs)
[![Docs.rs](https://docs.rs/momo-rs/badge.svg)](https://docs.rs/momo-rs)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

**Momo** is a general-purpose, high-performance async runtime for Rust, meticulously optimized for **thread-local affinity**, **cache locality**, and **zero atomic contention**.

---

## 🚀 Why Momo?

In traditional async runtimes like Tokio or smol, tasks are designed to be moved between threads (Work-Stealing). While powerful, this comes at a cost: **atomic synchronization overhead** and **L1/L2 cache bouncing**.

**Momo** takes a different approach: **Shared-Nothing Architecture**.

- **Task Pinning**: Tasks stay on the thread that created them.
- **Atomic-Free Internal**: Most internal scheduling logic uses `Rc` and `RefCell` instead of `Arc` and `Mutex`, eliminating lock contention.
- **Predictable Performance**: $O(1)$ timer management and generational I/O tokens ensure stable performance regardless of scale.

---

## 📦 Getting Started

### Installation

Add `momo-rs` to your `Cargo.toml`:

```toml
[dependencies]
momo-rs = "0.1"
```

### Basic Example

The simplest way to use Momo is via the `#[momo::main]` macro:

```rust
#[momo::main]
async fn main() {
    println!("Hello from Momo!");
    
    momo::spawn(async {
        println!("This task is pinned to the main thread.");
    });
}
```

---

## 🛠️ API Overview

### Task Management

| Function | Description |
| :--- | :--- |
| `momo::spawn` | Spawns a future onto the current thread's executor. |
| `momo::yield_now` | Voluntarily yields execution back to the scheduler. |
| `momo::stop` | Signals the local runtime to shut down. |

### Networking (TCP)

Momo provides a high-performance networking stack based on `mio`.

```rust
use momo::net::TcpListener;

#[momo::main]
async fn main() -> std::io::Result<()> {
    let listener = TcpListener::bind("127.0.0.1:8080".parse().unwrap())?;
    println!("Listening on 8080...");

    while let Ok((mut stream, addr)) = listener.accept().await {
        momo::spawn(async move {
            let mut buf = [0; 1024];
            if let Ok(n) = stream.read(&mut buf).await {
                let _ = stream.write(&buf[..n]).await;
            }
        });
    }
    Ok(())
}
```

### Timer Services

Momo uses a **4-level Hierarchical Timer Wheel** for $O(1)$ efficiency.

```rust
use core::time::Duration;

#[momo::main]
async fn main() {
    println!("Sleeping for 100ms...");
    momo::time::sleep(Duration::from_millis(100)).await;
    println!("Awake!");
}
```

---

## 🏗️ Architecture

### 🛡️ Generational I/O Tokens
To prevent the "ABA problem" (where a file descriptor is reused by the OS), Momo assigns a 64-bit ID to every socket. This ID combines a 32-bit index with a 32-bit generation counter. Stale events from old connections are automatically ignored.

### 🎡 O(1) Hierarchical Timer Wheel
Unlike runtimes that use binary heaps ($O(\log N)$), Momo uses a wheel structure. This ensures that inserting or expiring a timer takes the same amount of time whether you have 10 or 10,000,000 active timers.

### 🔌 Shared-Nothing Scheduler
Every thread in a Momo application runs its own independent executor. There is no global lock and no task migration, making Momo ideal for "Thread-per-Core" designs.

---

## 📊 Performance Comparison

Measured on single-threaded configurations (2026-04-21).

| Metric | Momo | Tokio (LocalSet) | Speedup |
| :--- | :--- | :--- | :--- |
| **Spawn Latency** | **169.74 ns** | 678.97 ns | **4.0x faster** |
| **MPSC Throughput** | **~7 ns / msg** | ~88 ns / msg | **12.5x faster** |
| **Yield Overhead** | **17.70 µs** | 77.54 µs | **4.4x faster** |

---

## 🛡️ License

Momo is licensed under the **MIT License**.

---

## 📖 Documentation

Full documentation is available at [docs.rs/momo-rs](https://docs.rs/momo-rs).
