nx_kv_arena.nx
buildroot/runtime/nx_kv_arena.nx
about
nx_kv_arena.nx -- PagedAttention page pool (bits-up).
vLLM's PagedAttention (UC Berkeley, SOSP'23) is the killer
LLM-serving algorithm: instead of one contiguous K/V buffer
per sequence, split into fixed-size PAGES. Each sequence owns
a list of page indices; pages can be SHARED across sequences
for prefix caching (e.g., shared system prompt = one cached
page); free pages return to the pool. vLLM published 24x
throughput over HuggingFace TGI on the same hardware.
THIS primitive is the page-pool substrate. K/V tensor data
itself is stored elsewhere (composes with shipped nx_kv_cache
for the tensor mechanics). This is the ALLOCATOR + INDEX
layer that makes paged-attention possible.
V1 scope:
- Fixed pool of NX_KV_ARENA_MAX_PAGES pages
- Each page is a fixed-size byte block (caller picks page_bytes
at arena_new time; typical 4 KiB for 16 tokens of f16 KV per
head)
- Sequence holds a list of page indices it owns (no sharing
in V1; prefix caching V2 adds refcount-on-pages)
- Pool exhaustion -> NULL append; caller handles (caller's
responsibility to evict via nx_lysosome or yield via
nx_yield_protocol)
- Canary-bracketed for tamper detection
Deferred to V2:
- Cross-sequence page sharing (refcount per page; prefix cache)
- Page eviction policy (LRU? attention-class? composes with
nx_attention_class)
- Dynamic page allocation (grow arena on demand)
- Multi-tier pages (GPU VRAM vs RAM vs NVMe; composes with
conductor cardinal)
genealogy_id: vllm_paged_attention_2023_sosp + s_lora_punica_2023 +
cardinal_2026-05-20_elder_ai_off_docker +
cardinal_2026-05-20_bits_up_nishi_not_linux
lineage_id: substrate_kv_arena_v1
dependencies 1 imports · 2 importers
imports: nx_syscalls.nx
imported by: nx_hackers_algo_compose_test.nxnx_kv_arena_test.nx
structs
| 107 | struct NxKvArena |
| 124 | struct NxKvSequence |
consts
| 67 | const NX_KV_ARENA_MAX_PAGES: i64 = 256 |
| 68 | const NX_KV_ARENA_MAX_SEQ_PAGES: i64 = 64 // max pages per sequence (V1) |
| 69 | const NX_KV_ARENA_DEFAULT_PAGE_B: i64 = 4096 // 4 KiB |
| 72 | const NX_KV_OK: i64 = 0 |
| 73 | const NX_KV_BAD_INPUT: i64 = 1 |
| 74 | const NX_KV_POOL_EXHAUSTED: i64 = 2 |
| 75 | const NX_KV_SEQ_FULL: i64 = 3 // per-seq page count exceeded |
| 76 | const NX_KV_TAMPER: i64 = 4 |
| 77 | const NX_KV_NOT_FOUND: i64 = 5 |
| 78 | const NX_KV_N_VERDICTS: i64 = 6 |
| 87 | const NX_KV_ARENA_CANARY_PRE: i64 = 0x4E584B56415250 // "NXKVARP\0" |
| 88 | const NX_KV_ARENA_CANARY_POST: i64 = 0x4E584B564152454E // "NXKVAREN" |
| 89 | const NX_KV_SEQ_CANARY_PRE: i64 = 0x4E584B5653455150 // "NXKVSEQP" |
| 90 | const NX_KV_SEQ_CANARY_POST: i64 = 0x4E584B5653454E45 // "NXKVSENE" |
| 93 | const NX_KV_PAGE_FREE: i64 = 0 |
| 94 | const NX_KV_PAGE_IN_USE: i64 = 1 |
functions
| 80 | func nx_kv_verdict_is_valid(v: i64) -> i64 called by 1: main |
| 139 | func nx_kv_arena_new(n_pages: i64, page_bytes: i64) -> *NxKvArena |
| 165 | func nx_kv_arena_is_valid(a: *NxKvArena) -> i64 |
| 180 | func _kv_arena_find_free(a: *NxKvArena) -> i64 called by 1: nx_kv_sequence_append_page |
| 190 | func nx_kv_sequence_new(arena: *NxKvArena, seq_id: i64) -> *NxKvSequence |
| 209 | func nx_kv_sequence_is_valid(s: *NxKvSequence) -> i64 |
| 224 | func nx_kv_sequence_append_page(s: *NxKvSequence) -> i64 |
| 251 | func nx_kv_sequence_share_page(s: *NxKvSequence, src_page_idx: i64) -> i64 |
| 273 | func nx_kv_arena_page_refcount(a: *NxKvArena, page_idx: i64) -> i64 |
| 284 | func nx_kv_sequence_free(s: *NxKvSequence) -> i64 |
| 315 | func nx_kv_arena_page_bytes(a: *NxKvArena, page_idx: i64) -> *u8 |
| 324 | func nx_kv_arena_n_in_use(a: *NxKvArena) -> i64 |
| 329 | func nx_kv_arena_n_free(a: *NxKvArena) -> i64 |
| 334 | func nx_kv_arena_n_pages(a: *NxKvArena) -> i64 |
| 339 | func nx_kv_sequence_n_pages(s: *NxKvSequence) -> i64 |