Skip to content

Commit 3b10560

Browse files
Match remade-with-rust portfolio conventions: hyphenated crate names, Mata Network homepage, portfolio README structure
1 parent d5f8ec9 commit 3b10560

11 files changed

Lines changed: 171 additions & 102 deletions

File tree

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ version = "0.1.0-alpha.1"
1818
edition = "2024"
1919
license = "MIT"
2020
repository = "https://github.com/remade-with-rust/rusty_alloc"
21-
# Part of the remade-with-rust portfolio — the org page is the front door, so
22-
# every crate points at it rather than only at its own repo.
23-
homepage = "https://github.com/remade-with-rust"
21+
# Portfolio convention (matches rusty_h264): homepage is Mata Network, the
22+
# parent org, not the GitHub org.
23+
homepage = "https://www.mata.network/"
2424
authors = ["remade-with-rust"]
2525
keywords = ["allocator", "malloc", "mimalloc", "memory", "no-std"]
2626
categories = ["memory-management", "no-std", "development-tools"]

README.md

Lines changed: 151 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,124 +1,189 @@
1+
[![crates.io](https://img.shields.io/crates/v/rusty_alloc.svg)](https://crates.io/crates/rusty_alloc)
2+
[![docs.rs](https://img.shields.io/docsrs/rusty_alloc)](https://docs.rs/rusty_alloc)
3+
[![CI](https://github.com/remade-with-rust/rusty_alloc/actions/workflows/ci.yml/badge.svg)](https://github.com/remade-with-rust/rusty_alloc/actions)
4+
[![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
5+
[![remade with rust](https://img.shields.io/badge/remade--with--rust-portfolio-orange.svg)](https://github.com/remade-with-rust)
6+
17
# rusty_alloc
28

3-
A pure-Rust remake of [mimalloc](https://github.com/microsoft/mimalloc) — the
4-
v2.4.5 architecture (32 MiB segments, free-list-sharded pages, lock-free
5-
cross-thread frees), rebuilt from the design rather than transliterated from
6-
the C.
9+
A ground-up, pure-**Rust** general-purpose **allocator** — the mimalloc v2.4.5
10+
architecture rebuilt from the design rather than transliterated from the C. No
11+
C in the dependency tree, permissive licence, and a safety property upstream
12+
does not offer.
13+
14+
## ⚡ The headline
715

8-
Part of the **[remade-with-rust](https://github.com/remade-with-rust)**
9-
portfolio, and built to its principles: memory safety first, no C in the
10-
product, general primitives over one-off fixes, and **measured, not vibed**
11-
which is why the performance section below spends as much space on what we
12-
*haven't* established as on what we have.
16+
- **Parity with mimalloc on instructions retired**, and ~16% fewer than glibc,
17+
on real programs under `LD_PRELOAD`.
18+
- **A double free aborts instead of corrupting.** Upstream mimalloc accepts it
19+
silently in release builds; we detect it on both the local and the
20+
cross-thread path and abort, for a measured ~0.4%.
21+
- **~150 of mimalloc's ~157 `mi_*` entry points**, gated against the C
22+
implementation as a differential oracle on every change.
23+
- **Runs on WebAssembly** with no C toolchain and no emscripten.
1324

1425
> **Status: `0.1.0-alpha.1`.** The allocator is complete and gated. The
15-
> performance *evidence* is not. Read
16-
> [What is and isn't measured](#what-is-and-isnt-measured) before depending on
17-
> this — the short version is that we count instructions, not seconds, and we
18-
> make no speed claim.
26+
> performance *evidence* is not. See
27+
> [What is and isn't measured](#what-is-and-isnt-measured) — we count
28+
> instructions, not seconds, and make no speed claim.
1929
20-
## What it is
30+
## Performance (this machine, deterministic)
2131

22-
- **~150 of mimalloc's ~157 `mi_*` entry points**, semantics-for-semantics,
23-
gated against the C implementation as a differential oracle.
24-
- **A double free is detected and aborted, not silently accepted.** Upstream
25-
mimalloc does not detect this in release builds. We do, at a measured cost of
26-
~0.4% on perl and ~0.2% on sqlite. Silently handing the same block to two
27-
owners is the exact failure this project exists to prevent, so the check is
28-
the point rather than an overhead.
29-
- **No C anywhere in the product.** The C mimalloc in this repo is a
30-
development-only oracle: never a dependency, never published.
31-
- **Runs on WebAssembly** (`wasm32-unknown-unknown`) with no C toolchain and no
32-
emscripten — `memory.grow`, single linear memory, gated by a self-test that
33-
executes inside a real VM.
32+
Instructions retired under callgrind, x86-64 Linux, real programs via
33+
`LD_PRELOAD`. Repeats to 4–6 significant figures.
3434

35-
## What is and isn't measured
35+
| workload | vs mimalloc | vs glibc |
36+
|---|---:|---:|
37+
| lua | **0.99** | 0.84 |
38+
| perl | **1.01** | 0.83 |
39+
| sqlite | **1.00** | 1.00 |
3640

37-
### Measured — instructions retired
41+
**Method.** `bench/icount-arms.sh`. Instruction counts, not wall-clock — chosen
42+
deliberately, because this machine's timing noise floor is wider than the
43+
effect (see below). Counts are immune to scheduler, thermal and load artifacts;
44+
they are also *not* a measure of time.
3845

39-
Deterministic (callgrind), x86-64 Linux, `LD_PRELOAD` against the real programs:
46+
### What is and isn't measured
4047

41-
| workload | vs mimalloc | vs glibc |
42-
|---|---:|---:|
43-
| lua | 0.99 | 0.84 |
44-
| perl | 1.01 | 0.83 |
45-
| sqlite | 1.00 | 1.00 |
48+
**Wall-clock: measured, and it cannot resolve the difference.**
49+
`bench/wallclock.sh` runs pinned, ABBA-interleaved, N=31, microsecond timer,
50+
with a **null arm** — the same allocator compared against itself:
51+
52+
| arm | median ratio |
53+
|---|---:|
54+
| **null (rusty_alloc vs ITSELF)** | **1.0117** |
55+
| perl, rusty_alloc vs mimalloc | 1.0009 |
56+
| sqlite, rusty_alloc vs mimalloc | 1.0091 |
4657

47-
Parity with mimalloc; roughly 16% fewer instructions than glibc. These repeat to
48-
4–6 significant figures, so they are claims we can defend.
58+
The null arm is **1.17%** — wider than either effect. The honest reading is
59+
**"at parity, below measurement resolution"**. Reproduce on a quiet box with
60+
`N=31 bash bench/wallclock.sh`.
4961

50-
### NOT measuredand therefore not claimed
62+
**Not measured, and therefore not claimed:**
5163

52-
- **Wall-clock time.** See [Timing](#timing) below. We have run it; this machine
53-
cannot resolve a difference this small, and we are not going to launder that
54-
into a speed claim.
55-
- **The full mimalloc-bench corpus.** Three workloads, not the suite. The
64+
- The full mimalloc-bench corpus. Three workloads, not the suite — the
5665
project's own v1 gate (geomean within 10%, no bench >25% behind, RSS within
5766
15%) is **not yet demonstrated**.
58-
- **RSS.** No systematic footprint sweep.
59-
- **aarch64.** The code paths exist and compile. They have never been executed.
67+
- RSS. No systematic footprint sweep.
68+
- aarch64. Code paths exist and compile; they have never been executed.
6069

6170
There is no "faster than mimalloc" claim anywhere in this repository, because
6271
the evidence for one does not exist yet.
6372

64-
### Timing
73+
## What is this?
6574

66-
`bench/wallclock.sh` runs pinned, ABBA-interleaved, microsecond-resolution
67-
comparisons at N=31 with a **null arm** — the same allocator against itself.
68-
The null arm is the floor: any delta smaller than it is noise, not a result.
75+
A reimplementation, not a binding. There are excellent mimalloc *bindings* for
76+
Rust; this is not one of them. Every line of the allocator is Rust, the C
77+
mimalloc in this repository is a development-only differential oracle, and it
78+
is never a dependency and never published.
6979

70-
Measured on the development machine (N=31, pinned, microsecond timer):
80+
`unsafe` is confined to the places an allocator genuinely needs it — the OS
81+
primitive layer, page and segment metadata, and the lock-free cross-thread
82+
protocol — with a stated invariant on every block, `unsafe_op_in_unsafe_fn`
83+
denied and `undocumented_unsafe_blocks` denied workspace-wide.
7184

72-
| arm | median ratio |
73-
|---|---:|
74-
| **null (rusty_alloc vs itself)** | **1.0117** |
75-
| perl, rusty_alloc vs mimalloc | 1.0009 |
76-
| sqlite, rusty_alloc vs mimalloc | 1.0091 |
85+
## The Remade With Rust ecosystem
7786

78-
The null arm is **1.17%** — wider than either measured effect. The same
79-
allocator compared against itself differs by more than the difference we are
80-
trying to detect, so the only honest reading is **"at parity, below measurement
81-
resolution"**. That is not a hedge; it is what the instrument supports.
82-
Reproduce it on a quiet box:
87+
| project | what |
88+
|---|---|
89+
| [rusty_alloc](https://github.com/remade-with-rust/rusty_alloc) | this — pure-Rust general-purpose allocator |
90+
| [rusty_h264](https://github.com/remade-with-rust/rusty_h264) | pure-Rust H.264 encoder and decoder |
91+
| [Mata Network](https://www.mata.network/) | the parent organisation |
8392

84-
```sh
85-
N=31 bash bench/wallclock.sh
93+
## Features
94+
95+
**Allocator core** — 32 MiB segments sliced into 64 KiB spans, free-list-sharded
96+
pages, the loom-verified four-state cross-thread free protocol, thread
97+
abandonment and adoption, first-class heaps, arenas, huge allocations, aligned
98+
allocation with interior-pointer recovery, and the full realloc family.
99+
100+
**Safety** — double-free detection on both the owner and cross-thread paths;
101+
Miri-clean; a 640-thread churn probe; `debug_checks` for full invariant
102+
validation; `secure` for guard pages, encrypted free lists and guarded-object
103+
sampling.
104+
105+
**Portability** — x86-64 and aarch64, Linux and Windows, plus
106+
`wasm32-unknown-unknown` via `memory.grow`.
107+
108+
## Install
109+
110+
```toml
111+
[dependencies]
112+
rusty_alloc-api = "0.1.0-alpha.1"
86113
```
87114

88-
## Layout
115+
| crate | docs | what |
116+
|---|---|---|
117+
| [`rusty_alloc`](https://crates.io/crates/rusty_alloc) | [docs.rs](https://docs.rs/rusty_alloc) | allocator core |
118+
| [`rusty_alloc-api`](https://crates.io/crates/rusty_alloc-api) | [docs.rs](https://docs.rs/rusty_alloc-api) | safe Rust surface — start here |
89119

90-
| path | what |
91-
|---|---|
92-
| `crates/rusty_alloc` | allocator core — **published** |
93-
| `crates/rusty_alloc_api` | safe Rust surface (`GlobalAlloc`, `Heap`, `Allocator`) — **published** |
94-
| `crates/rusty_alloc_ffi` | `mi_*`-compatible C ABI (cdylib + staticlib) |
95-
| `crates/rusty_alloc_override` | `malloc`/`free` interposition cdylib (LD_PRELOAD arm) |
96-
| `crates/rusty_alloc_bench` | Tier-B harness + trace record/replay |
97-
| `crates/rusty_alloc_wasm` | wasm self-test fixture |
98-
| `oracle/mimalloc` | C mimalloc @ v2.4.5 — **dev-only oracle**, never a runtime dep |
99-
| `corpus/mimalloc-bench` | the 1:1 benchmark corpus (submodule) |
100-
| `docs/LEDGER.md` | one entry per milestone: numbers, method, and every revert |
101-
| `docs/plans/rusty_alloc_v1.md` | plan of record — API inventory, gate ladder, roadmap |
102-
103-
Only the two crates marked **published** go to crates.io. Everything else is
104-
`publish = false`: harnesses, fixtures and native artifacts, not libraries.
120+
The FFI, LD_PRELOAD override, bench and wasm crates are `publish = false`:
121+
harnesses, fixtures and native artifacts, not libraries.
105122

106-
## Gates
123+
## Quick start
124+
125+
```rust
126+
use rusty_alloc_api::RustyAlloc;
107127

108-
Every change runs: Windows + Linux test suites (all features), `clippy -D
109-
warnings`, Miri, a 640-thread churn probe, a wasm VM self-test, and a
110-
deterministic instruction-count A/B against the C oracle. `docs/LEDGER.md`
111-
records what each milestone measured — **including the changes that were
112-
reverted for being flat or slower**, which is most of them.
128+
#[global_allocator]
129+
static ALLOC: RustyAlloc = RustyAlloc;
113130

114-
## Building the oracle (contributors)
131+
fn main() {
132+
let v: Vec<u64> = (0..1_000).collect();
133+
println!("{}", v.iter().sum::<u64>());
134+
}
135+
```
136+
137+
## Architecture
138+
139+
```
140+
crates/rusty_alloc allocator core (published)
141+
crates/rusty_alloc_api safe Rust surface (published)
142+
crates/rusty_alloc_ffi mi_*-compatible C ABI
143+
crates/rusty_alloc_override malloc/free interposition cdylib
144+
crates/rusty_alloc_bench Tier-B harness + trace record/replay
145+
crates/rusty_alloc_wasm wasm self-test fixture
146+
oracle/mimalloc C mimalloc @ v2.4.5 — dev-only oracle
147+
corpus/mimalloc-bench the 1:1 benchmark corpus
148+
docs/LEDGER.md one entry per milestone: numbers, method, reverts
149+
docs/plans/rusty_alloc_v1.md plan of record — API inventory, gate ladder
150+
```
151+
152+
## Benchmarking
115153

116154
```sh
117155
git submodule update --init oracle/mimalloc corpus/mimalloc-bench
118-
bash oracle/build.sh # builds mi / dmi / smi arms
156+
bash oracle/build.sh # build the C oracle arms
157+
bash bench/icount-arms.sh # deterministic instruction A/B
158+
N=31 bash bench/wallclock.sh # wall-clock, with a null arm
159+
bash bench/opscan.sh # per-operation scan vs mimalloc
119160
```
120161

162+
## Gates
163+
164+
Every change runs Windows + Linux suites (all features), `clippy -D warnings`,
165+
Miri, a 640-thread churn probe, a wasm VM self-test, and a deterministic
166+
instruction A/B against the C oracle. [`docs/LEDGER.md`](docs/LEDGER.md)
167+
records what each milestone measured — **including the changes reverted for
168+
being flat or slower**, which is most of them.
169+
170+
## Platform support
171+
172+
| target | status |
173+
|---|---|
174+
| x86-64 Linux | tested; the LD_PRELOAD and measurement path |
175+
| x86-64 Windows | tested |
176+
| aarch64 | compiles; **never executed** |
177+
| wasm32-unknown-unknown | tested in a VM self-test |
178+
121179
## License
122180

123-
MIT — see [LICENSE](LICENSE). Vendored dev-only dependencies keep their own
124-
licenses; none of them ship.
181+
MIT — see [LICENSE](LICENSE). No GPL or LGPL anywhere in the tree. The vendored
182+
oracle and benchmark corpus are development-only, keep their own licences, and
183+
never ship.
184+
185+
## About Mata Network
186+
187+
rusty_alloc is part of the [remade-with-rust](https://github.com/remade-with-rust)
188+
portfolio from [Mata Network](https://www.mata.network/): foundational software
189+
rebuilt in Rust, memory-safe by construction, measured rather than asserted.

bench/rebuild-measure.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ set -uo pipefail
66
cd "$(cd "$(dirname "$0")/.." && pwd)" || exit 1
77
export CARGO_TARGET_DIR="$HOME/ra_target"
88
echo "== build"
9-
if ! cargo build --release -p rusty_alloc_override 2>&1 | tail -6; then
9+
if ! cargo build --release -p rusty_alloc-override 2>&1 | tail -6; then
1010
echo "BUILD FAILED"
1111
exit 1
1212
fi

bench/tls-ceiling.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ cd "$root"
2020

2121
echo "building initial-exec variant..."
2222
RUSTFLAGS='-Z tls-model=initial-exec' CARGO_TARGET_DIR="$HOME/ra_ie" \
23-
cargo +nightly build --release -p rusty_alloc_override 2>&1 | grep -E '^error' | head -5
23+
cargo +nightly build --release -p rusty_alloc-override 2>&1 | grep -E '^error' | head -5
2424

2525
IE="$HOME/ra_ie/release/librusty_alloc_override.so"
2626
GD="$HOME/ra_target/release/librusty_alloc_override.so"

corpus/wasm-gate.ps1

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# `cargo test` cannot execute wasm32-unknown-unknown, so correctness is proven
44
# by instantiating the cdylib under Node and calling its self-test export. The
5-
# same self-test also runs natively via `cargo test -p rusty_alloc_wasm`, so a
5+
# same self-test also runs natively via `cargo test -p rusty_alloc-wasm`, so a
66
# failure here is specifically a WASM failure.
77
#
88
# Exits non-zero on any failure, so it can be chained into the gate battery.
@@ -14,9 +14,11 @@ cargo check -p rusty_alloc --target wasm32-unknown-unknown
1414
if ($LASTEXITCODE -ne 0) { Write-Host "WASM GATE FAILED: core crate does not compile"; exit 1 }
1515

1616
Write-Host "== build selftest cdylib"
17-
cargo build -p rusty_alloc_wasm --target wasm32-unknown-unknown --release
17+
cargo build -p rusty_alloc-wasm --target wasm32-unknown-unknown --release
1818
if ($LASTEXITCODE -ne 0) { Write-Host "WASM GATE FAILED: selftest build"; exit 1 }
1919

20+
# NOTE: the PACKAGE is `rusty_alloc-wasm`, but cargo maps the hyphen to an
21+
# underscore for the artifact, so the file is `rusty_alloc_wasm.wasm`.
2022
$wasm = "target\wasm32-unknown-unknown\release\rusty_alloc_wasm.wasm"
2123
if (-not (Test-Path $wasm)) { Write-Host "WASM GATE FAILED: $wasm not produced"; exit 1 }
2224

crates/rusty_alloc/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[package]
22
name = "rusty_alloc"
3-
description = "Pure-Rust remake of mimalloc v2.4.5 — allocator core"
3+
description = "Allocator core of the rusty_alloc pure-Rust remake of mimalloc v2.4.5: segments, free-list-sharded pages, lock-free cross-thread frees, first-class heaps, arenas and a mi_*-compatible surface. Detects double frees. MIT."
4+
documentation = "https://docs.rs/rusty_alloc"
45
version.workspace = true
56
edition.workspace = true
67
license.workspace = true

crates/rusty_alloc_api/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[package]
2-
name = "rusty_alloc_api"
3-
description = "Safe Rust-native surface over rusty_alloc: GlobalAlloc, Heap, Allocator"
2+
name = "rusty_alloc-api"
3+
description = "Safe Rust surface for the rusty_alloc pure-Rust mimalloc remake: GlobalAlloc, first-class Heap, and the Allocator trait. No unsafe required of callers. MIT."
4+
documentation = "https://docs.rs/rusty_alloc-api"
45
version.workspace = true
56
edition.workspace = true
67
license.workspace = true

crates/rusty_alloc_bench/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[package]
2-
name = "rusty_alloc_bench"
2+
name = "rusty_alloc-bench"
33
description = "Tier-B native harness + allocation-trace record/replay + G1/G2 gates"
44
version.workspace = true
55
edition.workspace = true
@@ -17,7 +17,7 @@ path = "src/main.rs"
1717
rusty_alloc = { path = "../rusty_alloc" }
1818

1919
[dev-dependencies]
20-
rusty_alloc_api = { path = "../rusty_alloc_api" }
20+
rusty_alloc-api = { path = "../rusty_alloc_api" }
2121
libloading = "0.8"
2222

2323
[lints]

crates/rusty_alloc_ffi/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[package]
2-
name = "rusty_alloc_ffi"
2+
name = "rusty_alloc-ffi"
33
description = "mi_*-compatible C ABI over rusty_alloc (cdylib + staticlib)"
44
version.workspace = true
55
edition.workspace = true

crates/rusty_alloc_override/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[package]
2-
name = "rusty_alloc_override"
2+
name = "rusty_alloc-override"
33
description = "malloc/free interposition cdylib (LD_PRELOAD arm for the 1:1 corpus)"
44
version.workspace = true
55
edition.workspace = true
@@ -15,7 +15,7 @@ crate-type = ["cdylib", "rlib"]
1515

1616
[dependencies]
1717
rusty_alloc = { path = "../rusty_alloc" }
18-
rusty_alloc_ffi = { path = "../rusty_alloc_ffi" }
18+
rusty_alloc-ffi = { path = "../rusty_alloc_ffi" }
1919

2020
[lints]
2121
workspace = true

0 commit comments

Comments
 (0)