101 lines
4.0 KiB
Markdown
101 lines
4.0 KiB
Markdown
# smarm
|
|
|
|
> SMARM — Smarm, Marks Actor Runtime Machinery. A proof-of-concept green-thread actor runtime for Rust.
|
|
|
|
Implements the core ideas in [`Achitecture.md`](.docs/Architecture.md): green-thread actors on a
|
|
shared heap, scheduled cooperatively, communicating only by `Send` messages.
|
|
Erlang's isolation model without Erlang's copying GC, Rust's zero-copy
|
|
ownership transfers without async's function colouring.
|
|
|
|
The scheduler is multi-threaded — one OS thread per available CPU, all drawing
|
|
from a shared run queue. The single-threaded `run()` entry point is kept as a
|
|
convenience wrapper around `runtime::init(Config::exact(1)).run(f)`.
|
|
|
|
## What's here
|
|
|
|
| Module | What it does |
|
|
|--------------|------------------------------------------------------------------------|
|
|
| `stack` | `mmap`'d growable stack with guard page; SIGSEGV on overflow |
|
|
| `context` | `#[naked]` x86-64 context-switch shims, callee-saved regs only |
|
|
| `preempt` | Allocator-driven preemption; `check!()` macro for no-alloc loops |
|
|
| `pid` | `(index, generation)` PIDs; stale handles are detectable, not silent |
|
|
| `actor` | Trampoline + `catch_unwind` boundary at the actor entry point |
|
|
| `scheduler` | Run queue, slot table, spawn/join, parking, idle path |
|
|
| `channel` | Unbounded MPSC channel; `recv` parks the actor |
|
|
| `mutex` | `Mutex<T>` with mandatory timeout; FIFO waiters; parks the green thread |
|
|
| `timer` | Min-heap of `(deadline, reason)`; `Sleep` and `WaitTimeout` reasons |
|
|
| `io` | `block_on_io` for blocking work; `wait_readable`/`wait_writable` + `read`/`write` via epoll |
|
|
| `supervisor` | `Signal::Exit` / `Signal::Panic` delivered to a parent actor's mailbox |
|
|
|
|
## Quick taste
|
|
|
|
```rust
|
|
use smarm::{run, spawn, channel};
|
|
|
|
run(|| {
|
|
let (tx, rx) = channel::<i64>();
|
|
let h = spawn(move || {
|
|
for _ in 0..3 {
|
|
let v = rx.recv().unwrap();
|
|
println!("got {v}");
|
|
}
|
|
});
|
|
for v in 1..=3i64 {
|
|
tx.send(v).unwrap();
|
|
}
|
|
h.join().unwrap();
|
|
});
|
|
```
|
|
|
|
## Layout
|
|
|
|
```
|
|
src/
|
|
stack.rs context.rs preempt.rs pid.rs actor.rs
|
|
scheduler.rs channel.rs mutex.rs timer.rs io.rs supervisor.rs
|
|
lib.rs
|
|
tests/
|
|
per-module integration tests
|
|
benches/
|
|
primes.rs fan-out/fan-in compute, vs tokio current_thread
|
|
```
|
|
|
|
## Building and running
|
|
|
|
Standard Cargo. Requires Rust 1.95 or newer (the `#[naked]` attribute went stable
|
|
in 1.88; we use a few unrelated post-1.88 features). x86-64 Linux only —
|
|
ARM64 and macOS are on the deferred list because of the assembly shim and the
|
|
epoll dependency.
|
|
|
|
```sh
|
|
cargo test # all tests
|
|
cargo test --test mutex # one module
|
|
cargo bench # primes benchmark vs tokio
|
|
```
|
|
|
|
## What's not here
|
|
|
|
See the **Defer** section of `Architecture.md`.
|
|
restart-intensity caps, `join!` for handle groups, stack growth via remap,
|
|
hierarchical timer wheel, fd-wait timeouts, `Signal::Timeout`. Each is
|
|
mechanism we know how to add; none belongs in this iteration.
|
|
|
|
## Docs
|
|
|
|
| Document | What it covers |
|
|
|---|---|
|
|
| [`Architecture.md`](./docs/Architecture.md) | Design intent, runtime model, and deferred work |
|
|
| [`smarm - Deep Dive.html`](./docs/smarm%20-%20Deep%20Dive.html) | Generated walkthrough of the system; good starting point |
|
|
| [`BENCHMARKS_AND_TUNING.md`](./docs/BENCHMARKS_AND_TUNING.md) | Where smarm wins and loses vs tokio, preemption knob recommendations |
|
|
| [`benchmarks.md`](./docs/benchmarks.md) | Raw benchmark results, methodology, and tuning experiment log |
|
|
|
|
## Contributing
|
|
|
|
This is a personal proof-of-concept. There's no PR workflow — if you fork it
|
|
and do something interesting, just send me an email. I'd genuinely like to
|
|
hear about it.
|
|
|
|
---
|
|
|
|
<sub>The name is a recursive acronym. The M is for Marks, as in the BEAM — Bogdan/Björn's Erlang Abstract Machine, the virtual machine that runs Erlang and Elixir. smarm is not the BEAM. It just admires it from a safe distance.</sub>
|