{"id":47422457,"url":"https://github.com/rhetro/ordex","last_synced_at":"2026-04-04T22:01:14.665Z","repository":{"id":341189563,"uuid":"1169311324","full_name":"rhetro/ordex","owner":"rhetro","description":"A strict, generational arena allocator for Rust","archived":false,"fork":false,"pushed_at":"2026-02-28T13:56:00.000Z","size":19,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-30T15:28:27.930Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rhetro.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-28T13:51:31.000Z","updated_at":"2026-03-13T13:57:32.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/rhetro/ordex","commit_stats":null,"previous_names":["rhetro/ordex"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/rhetro/ordex","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhetro%2Fordex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhetro%2Fordex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhetro%2Fordex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhetro%2Fordex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rhetro","download_url":"https://codeload.github.com/rhetro/ordex/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhetro%2Fordex/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31416324,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T20:09:54.854Z","status":"ssl_error","status_checked_at":"2026-04-04T20:09:44.350Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-03-21T17:00:28.996Z","updated_at":"2026-04-04T22:01:14.655Z","avatar_url":"https://github.com/rhetro.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# Ordex\n\n**Ordex** is a strict, generational arena allocator for Rust designed for systems programming. \n\nIt provides a safe, deterministic architecture to manage lifecycles and handle simultaneous mutable access to multiple disparate elements—bypassing the need for runtime borrow checking overhead like `Rc\u003cRefCell\u003cT\u003e\u003e` while strictly enforcing Rust's aliasing rules.\n\n## Core Philosophy\n\nWhen building non-linear architectures or cross-cutting domain logic (e.g., AST manipulation, network multicast routing, or ECS), you frequently require simultaneous mutable access to multiple disparate nodes. Standard Rust collections reject this because the compiler cannot prove index disjointness at compile time.\n\nOrdex solves this through two distinct mechanical approaches, split explicitly by their algorithmic thresholds:\n\n1. **Targeted Alignment (`align!`):** Extracts up to 16 distinct mutable references simultaneously. Verification is done via fixed-size stack arrays. This macro is strictly capped at `N=16` because, within this exact boundary, LLVM auto-vectorization (SIMD) and modern CPU branch predictors execute the array checks in effectively `O(1)` time with zero memory allocations.\n2. **Batch Ordering (`ordex`):** Provides safe, batch mutable access for dynamically generated target lists. Beyond `N=16`, the `O(N^2)` unrolled comparisons bloat the instruction cache. Therefore, this fallback API brings order to chaos via `O(N log N)` sorting and linear `O(N)` sweep validation, which becomes mathematically strictly superior for larger datasets.\n3. **Strict ABA Prevention:** Uses generational indices to physically block access from stale pointers (dangling indices).\n\n## The Aliasing Trilemma (Why Ordex?)\n\nIn system programming with Rust (e.g., graphs, ECS, network routing, or GUI widget trees), simultaneous mutable access to multiple disparate nodes typically forces a compromise between **Safety**, **Performance**, and **Ergonomics**.\n\nExisting approaches resolve this by sacrificing at least one:\n\n* **The Runtime Overhead (`Rc\u003cRefCell\u003cT\u003e\u003e`)**: Maintains safety and ergonomics but severely degrades performance in tight loops. Every access incurs reference counter updates and dynamic borrow flag checks, polluting the CPU cache line. This creates a severe bottleneck for high-throughput routing, high-FPS simulations, or complex GUI state propagation.\n* **Manual Unsafe in Application Code (Raw Pointers)**: Achieves maximum performance but bypasses compiler-guaranteed memory safety. The programmer assumes full liability for ABA problems, aliasing violations, and undefined behavior.\n* **Traditional Arenas (`slotmap`, `generational-arena`)**: Highly optimized for single-element access or iteration. However, they lack zero-allocation, safe APIs for simultaneous mutable access to 3 or more elements. You are forced to allocate temporary structures for runtime checks or use awkward extract-and-return patterns.\n\n**Ordex breaks this trilemma through hardware-friendly static arrays and amortized dynamic batching.**\nInstead of relying on generic software abstractions (like runtime state management), Ordex provides two distinct mechanical approaches:\n\n1. **Static Validation (`align!`)**: For known, small targets (capped at `N=16`), it maps the safety validation to fixed-size stack arrays. This leverages LLVM auto-vectorization (SIMD) to resolve the `O(N^2)` aliasing verification in parallel, resulting in effectively `O(1)` execution time and strictly zero heap allocation.\n2. **Dynamic Validation (`ordex`)**: For dynamic or large sets (e.g., spatial queries), it uses `O(N log N)` sorting and linear scanning over a reusable buffer. This guarantees safe multi-mutable iteration without cache-polluting borrow flags, achieving amortized zero heap allocation.\n\nTogether, they provide strict compiler safety and ergonomic multi-mutable access without requiring per-access heap allocations.\n\n## Performance Proof: Hitting the Hardware Limit\n\nOrdex is designed to map directly to CPU hardware capabilities, completely eliminating software abstraction overhead. Benchmarks prove that Ordex's latency is bounded strictly by physical memory access (Memory Wall), not by safety validation.\n\n**1. Static Alignment (`align!` for N=16)**\n* **Optimal Cache (L1 Hit):** `~129 ns` total (~8 ns per element).\n* **Extreme Cache Miss (Forced L2/L3 DRAM fetch):** `~327 ns` total (~20 ns per element).\n* **Conclusion:** 20ns aligns perfectly with the physical latency of fetching from L3/DRAM. The array-based `O(N^2)` safety check is entirely hidden by CPU out-of-order execution during the memory stall.\n\n**2. Dynamic Batching (`ordex` for N=1000)**\n* **Extreme Cache Miss:** `~91 µs` total (~91 ns per element).\n* **Conclusion:** Even under extreme fragmentation, extracting 1,000 completely random mutable references—including `O(N log N)` sorting, deduplication, and generation verification—completes in under 100 microseconds with **strictly zero allocations**. \n\n## Real-World Application: Wasm Boids Simulation\n\nTo demonstrate Ordex's capability in a highly dynamic and constrained environment, I implemented a continuous Lotka-Volterra (Boids) running entirely in the browser via WebAssembly.\n\n* **Workload:** 3,500+ active entities (predators and prey) continuously spawning, moving, and being removed.\n* **Interactions:** Dynamic spatial hashing where nodes resolve simultaneous mutable state changes with 5+ neighbors per frame.\n* **Performance:** Maintains a stable 100 FPS (capped by display Vsync) on a single Wasm thread.\n* **Memory Profile:** Reuses internal buffers (`clear_and_verify`) to prevent per-frame heap allocations during the simulation loop, avoiding allocator overhead and heap fragmentation.\n\n▶️ **Live Demo (Play in Browser):** [Non-Linear Network Boids Simulation (Lotka-Volterra Model / Rust + Wasm)](https://rhetro.pages.dev/rust/ordex/)\n\n## Comparison\n\nHow does Ordex compare to standard Rust patterns and existing arena allocators?\n\n| Feature | `Rc\u003cRefCell\u003cT\u003e\u003e` | Standard Arenas (e.g., generational) | **Ordex** |\n| :--- | :--- | :--- | :--- |\n| **Simultaneous Mutable Access** | Impossible (Runtime Panic) | Limited (usually 1-2 elements via `get2_mut`) | **Up to 16 (Static) or N (Dynamic)** |\n| **Runtime Overhead** | Heavy (Ref counts \u0026 flag updates) | Low (Bounds \u0026 generation checks) | **Minimal (Verified upfront, register-level checks after)** |\n| **Memory Efficiency** | Bloated (Pointers + counters) | High | **Highly Compact (8-byte NPO Index)** |\n| **Architecture** | Decentralized \u0026 Chaotic | Centralized, but strict aliasing limits | Centralized \u0026 **Non-Linear** Multi-mutable |\n\n## Key Features\n\n* **Strict Aliasing Prevention**: Automatically panics if you attempt to request multiple mutable references to the same physical memory index, preventing silent data corruption.\n* **Generational Tracking**: Every memory slot tracks its generation. Reused slots increment their generation, making old indices instantly invalid.\n* **Zero-Allocation Dynamic Batching**: Dedicated API (`clear_and_verify`) allows reusing internal buffers for dynamic target resolution, achieving zero heap allocations during tight loops (e.g., game ECS ticks).\n* **Fail-Fast vs. Safe Observation**: Distinct API boundaries between absolute enforcement (`align!` / `ordex`, which panic on stale access) and safe observation (`get` / `get_mut`, which return `Option`).\n* **Null Pointer Optimization (NPO)**: Uses `NonZeroU32` for generation tracking by default, ensuring that `Option\u003cIndex\u003e` remains exactly 8 bytes. Eliminates enum tag overhead and maximizes CPU cache efficiency.\n\n## Quick Start\n\nAdd Ordex to your `Cargo.toml`:\n\n```toml\n[dependencies]\nordex = \"0.1.0\"\n```\n\n### Basic Usage: Targeted Alignment\n\n```rust\nuse ordex::prelude::*;\n\n#[derive(Debug)]\nstruct Node {\n    value: i32,\n}\n\nfn main() {\n    let mut arena = OrdexArena::new();\n\n    // 1. Insert elements\n    let idx_a = arena.insert(Node { value: 10 });\n    let idx_b = arena.insert(Node { value: 20 });\n    let idx_c = arena.insert(Node { value: 30 });\n\n    // 2. Static Alignment: Safely mutate distinct elements simultaneously\n    align!(arena, idx_a, idx_b, |a, b| {\n        a.value += 5;\n        b.value *= 2;\n    });\n\n    assert_eq!(arena.get(idx_a).unwrap().value, 15);\n    assert_eq!(arena.get(idx_b).unwrap().value, 40);\n\n    // 3. Memory Reuse \u0026 Generation Tracking\n    arena.remove(idx_a); // Slot becomes Free\n\n    // Reuses the physical slot of idx_a, but advances the generation\n    let idx_new = arena.insert(Node { value: 99 }); \n\n    // Attempting to access the old index will result in a safe panic,\n    // completely preventing the ABA problem.\n    // align!(arena, idx_a, idx_c, |a, c| { ... }); // PANICS!\n}\n```\n\n### Dynamic Batch Processing (Zero Allocation)\n\nFor scenarios where the targets are determined at runtime (e.g., multicast network routing, Area-of-Effect in games):\n\n```rust\nuse ordex::prelude::*;\n\nfn main() {\n    let mut arena = OrdexArena::\u003ci32\u003e::new();\n    let i0 = arena.insert(100);\n    let i1 = arena.insert(200);\n    let i2 = arena.insert(300);\n\n    // Dynamic targets determined at runtime\n    let targets = vec![i2, i0];\n    \n    // VerifiedIndices ensures no aliasing and sorts indices for optimal sequential access.\n    // Make it mutable so we can reuse the allocated buffer later.\n    let mut verified = VerifiedIndices::new(targets);\n\n    // Bring \"Ordex\" (Order) to the dynamic list and mutate them in batch\n    arena.ordex(\u0026verified, |mut iter| {\n        while let Some(value) = iter.next() {\n            *value += 50;\n        }\n    });\n\n    // In the next frame/tick, reuse the buffer to STRICTLY PREVENT memory allocations.\n    // This is vital for ECS or high-frequency game loops.\n    let new_targets = vec![i1, i2];\n    verified.clear_and_verify(\u0026new_targets); // Modified: Pass by slice reference\n    \n    arena.ordex(\u0026verified, |mut iter| {\n        // Safe, zero-allocation batch mutation\n    });\n}\n```\n\n## API Boundaries\n\nOrdex enforces a strict contract regarding how you access data:\n\n* **Use `align!` / `ordex`** when your domain logic *guarantees* the targets must exist. If a target is missing or aliased, it indicates a critical state synchronization bug, and Ordex will **panic** to fail-fast.\n* **Use `get` / `get_mut`** when the target's existence is asynchronous or uncertain (e.g., UI updates, async task cancellation). It safely returns an `Option\u003cT\u003e`.\n\n## Real-world Scenarios\n\nCheck out the `tests/` directories for executable documentation on applying Ordex to various domains:\n* Compiler AST manipulation (Constant Folding)\n* Network Session Multiplexing\n* Async Task Scheduler / Worker Pools\n* Entity Component System (ECS) Combat simulations\n\n## Architectural Limits \u0026 Feature Flags\n\nTo maintain a compact 8-byte footprint for the `Index` struct and optimize CPU L1/L2 cache usage, Ordex uses `u32` for indices and `NonZeroU32` for generations by default. This default design introduces two hard limits:\n\n1. **Maximum Capacity (Index Overflow):** The `OrdexArena` can hold a maximum of 4,294,967,295 (`u32::MAX`) active elements simultaneously. Attempting to insert more elements than this will explicitly panic (fail-fast) to strictly prevent silent memory corruption and UB.\n2. **Generation Wrap-around (The ABA Edge Case):** If a *single specific physical memory slot* is freed and reused exactly 4,294,967,296 times, its generation counter will wrap around to 1. For short-lived applications or standard games, reaching this is practically impossible. However, highly active systems running continuously for months (e.g., game servers, routers) *can* hit this boundary on frequently recycled slots.\n\n### Feature Flags: Extended Generation Tracking\nIf you are building long-running infrastructure where strict mathematical safety against the ABA problem is required over maximum CPU cache efficiency, opt into 64-bit indices:\n\n```toml\n[dependencies]\nordex = { version = \"0.1.0\", features = [\"large-indices\"] }\n```\n\nThis forces the `Index` to use `u64` and `NonZeroU64` (16 bytes in total). This extends the generational wrap-around horizon far beyond the lifespan of the universe, providing strict safety for enterprise-grade continuous uptimes.\n\n## License\n\nThis project is licensed under either of\n\n* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0))\n* MIT license ([LICENSE-MIT](LICENSE-MIT) or[http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT))\n\nat your option.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frhetro%2Fordex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frhetro%2Fordex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frhetro%2Fordex/lists"}