# Evaluated Applications — full package docs This file concatenates the plain-text content of every published Evaluated Applications package's owner-authored source doc (`MonoRepo//docs/site.md`), verbatim except for markdown-to-plain reflow. It exists so an AI system can read every package's own words in one request instead of crawling twelve pages. Each package's own page (linked below) may present this same content with additional design/rendering; the words below are the package owner's source of truth. Every package named here is on NuGet under a commercial licence — evaluation and non-commercial use are permitted without one, and no feature named in this file is gated behind a tier or a license key. See https://evaluatedapplications.github.io/packages.html#license for the full terms. See https://evaluatedapplications.github.io/llms.txt for the short summary, tool list, and our partnership offer (we pay third parties to build on this stack). ================================================================================ # Phasor — EvaluatedApplications.Phasor Page: https://evaluatedapplications.github.io/phasor.html Install: dotnet add package EvaluatedApplications.Phasor ================================================================================ Encode numbers and symbols as phasor faces, then compose them with one algebra instead of a calculator. Phasor is a Vector Symbolic Architecture (VSA) codec for .NET. It represents tokens (numbers and text) as bundles of unit complex numbers called phasors. Composition (bind), decomposition (unbind), superposition (bundle), and readout (correlation) form the complete algebra; arithmetic is encoding, not calculation. The problem it solves: symbolic and numeric data are usually kept separate — numbers flow through arithmetic circuits, symbols through lookup tables. Phasor bridges them. Bind two numbers on the linear band and you add them; bind on the log band and you multiply them. A symbol encodes to a fixed random phasor. Now both live in the same algebra: you can store them together, mix them, and read values back by correlation. This is the substrate for exact storage (no floating-point error in bundle/delete), similarity search at scale, and models that reason over both values and symbols with the same composition operators. How it works: Encode — a number becomes a face with its value encoded as phase (deterministic); a symbol gets a salted hash-based random signature. Compose — bind (complex multiply per component) builds relationships; bundle (sum) collects sets or superpositions; unbind (conjugate) extracts parts exactly; readout by correlation gives a dot-product score. On the linear band, bind is addition; on the log band, it's multiplication — arithmetic IS the composition. Two profiles: PhasorCodec is fixed-width (256 reals) with a frozen identity prefix and a learned orbital tail, built for neural models. HoloCodec is configurable width, SIMD (Vector), a planar layout, and a memoized number cache, built for holographic storage and similarity search at scale. Do not mix faces between the two. The Hologram type wraps a phasor face and applies the algebra through operators (*, +, /, ~) for readability and prototyping; in-place static methods (BindInto, BundleInto, UnbindInto) are for hot loops (operators allocate; measured ~1.7x slower at d=64-96). Check the live NuGet listing (EvaluatedApplications.Phasor) for the exact current version. Minimal example: ```csharp using Phasor; double[] five = PhasorCodec.Encode("5"); double[] greeting = PhasorCodec.Encode("hello"); double[] five_plus_three = PhasorCodec.Bind(five, PhasorCodec.Encode("3")); int sum = PhasorCodec.DecodeSum(five_plus_three, max: 10); // sum == 8 double[] pair = PhasorCodec.Bundle(greeting, five); double[] extracted = PhasorCodec.Unbind(pair, greeting); // extracted is close to five ``` Key features: one algebra with no special cases; exact composition (bundle/unbind are exact, subtraction removes a contribution with no floating-point error); two profiles for different workloads; no dependencies beyond System/System.Numerics; AOT and trim compatible; deterministic (not cryptographic) hashing; a memoized decode cache. Compatibility: .NET 8.0 and 10.0, Windows/Linux/macOS, no platform-specific code, dependency-free. License: proprietary — evaluation and non-commercial use are permitted; commercial use requires a commercial licence; no feature is gated in code. ================================================================================ # EvalApp — EvaluatedApplications.EvalApp Page: https://evaluatedapplications.github.io/evalapp.html Install: dotnet add package EvaluatedApplications.EvalApp ================================================================================ A self-tuning, resource-gated async pipeline runtime for .NET — describe a process as data and steps, and stop hand-writing concurrency coordination. What it does: EvalApp replaces the plumbing every real async .NET codebase ends up writing by hand — a SemaphoreSlim to stop a flood of requests hammering a database, a guessed constant for "how many things run at once," a Task.WhenAll wrapped in try/catch to aggregate failures, a rollback path bolted on after something breaks halfway through. You describe a process as a plain data record and a sequence of steps; EvalApp compiles that into a single, reusable execution path, gates every resource it touches (CPU, network, disk, database, or a custom pool) at a real bound, and — when you turn tuning on — discovers the concurrency that actually works on the hardware it's running on. It's the shared runtime under every Evaluated Applications product, and it works standalone: no broker, no external service, no config store. Why it's useful: one in-process dependency instead of a stack (DI container + MediatR + Polly + TPL Dataflow); the tuner is proactive, continuously probing for the operating point that keeps things from breaking rather than reacting after something breaks; whole categories of coordination bugs don't compile (a saga must close before the pipeline builds; a side-effecting step can't be added without declaring its resource); the builder chain reads like the process it describes; nothing to stand up first. Targets net8.0 and net10.0, binary-only, zero dependencies. Check the live NuGet listing (EvaluatedApplications.EvalApp) for the exact current version. Key features: fluent pipeline builder; resource-gated concurrency; adaptive and Bayesian tuning; parallel ForEach and parallel branches; sagas with compensation; middleware (retry, timeout, circuit breaker, timing, audit, validation); results as data (PipelineResult), not exceptions; an offline licensing facade (ECDsa P-256, no network call, ever). Useful to know: no feature in EvalApp is gated behind a tier or a license key today. License: proprietary — evaluation and non-commercial use are permitted; commercial use requires a commercial licence. Compatibility: .NET 8 and .NET 10, no third-party package references. Minimal example: ```csharp using EvalApp; public sealed record OrderData(string CustomerName, decimal Total, string Status = "New"); Eval.App("Orders") .DefineDomain("Orders") .DefineTask("ProcessOrder") .AddStep("Validate", d => d with { Status = "Validated" }) .AddStep("ApplyDiscount", d => d with { Total = d.Total * 0.9m }) .AddStep("Complete", d => d with { Status = "Complete" }) .Run(out ICompiledPipeline pipeline) .Build(); // no license key needed — nothing is license-gated today var result = await pipeline.RunAsync(new OrderData("Alice", 99.99m)); ``` Build the pipeline once (e.g. at startup); call RunAsync many times. Design first, code second: decide the data record before touching the builder. Where it doesn't fit: long-running workflows that must survive a process restart over hours/days are Temporal's job; purely reactive resilience is what Polly is for. EvalApp is for throughput-sensitive work with no infrastructure to stand up and concurrency that should tune itself. ================================================================================ # EvalApp.Neural — EvaluatedApplications.EvalApp.Neural Page: https://evaluatedapplications.github.io/evalapp-neural.html Install: dotnet add package EvaluatedApplications.EvalApp.Neural ================================================================================ Real-time neural tuning for data-parallel pipelines. Problem: EvalApp's built-in concurrency tuner works well on clean, predictable workloads but falls flat when conditions shift or gates couple (database racing CPU racing disk). You either tune once and hope, or freeze the tuning and regret it later. Solution: EvalApp.Neural plugs a tiny, always-learning neural policy into EvalApp in place of the heuristic. It trains on a real workload's own experience, so it adapts live as conditions change. Ships warm (pre-trained on diverse scenarios) and keeps learning from every decision. Fast (about 0.4ms per decision) and low overhead. Why it works: online learning reacts to real-time shifts a frozen heuristic can't; matches the built-in heuristic on lean/obvious pipelines (no edge there) but beats it roughly 25% on coupled multi-gate benchmarks; opt-in with no refactor — add .WithNeuralTuning() to the app builder. Version: v1.0.1. How to use: ```csharp var app = Eval.App(...).WithResource(...).WithNeuralTuning().DefineDomain(...); ``` Install it globally for every app: ```csharp using var _ = NeuralTuning.UseGlobally(NeuralTuning.NewModel()); ``` Or train on your own workload by pointing a shared model file at every runner: ```csharp using var _ = NeuralTuning.UseGloballyPersisted("model.bin"); ``` Key features: warm-start (ships pre-trained, nothing to configure); always learning (real-time adaptation, no manual retuning); tiny footprint (a small holographic model via AlgFormer, roughly 0.4ms/decision); no license gate — runs at full effect regardless of license tier; production ready (coordinate descent for multi-gate coupling, deterministic under a repeated seed). What you need to know: best on coupled/noisy workloads — clean single-gate CPU-bound pipelines won't see much gain. Depends on EvalApp and AlgFormer (bundled, no separate install). Compatible with .NET 8.0+, Windows/Linux. ================================================================================ # AlgFormer — EvaluatedApplications.AlgFormer Page: https://evaluatedapplications.github.io/algformer.html Install: dotnet add package EvaluatedApplications.AlgFormer ================================================================================ A transformer engine with two interchangeable attention cores — one classic, one holographic — in pure managed code, no external ML runtime. AlgFormer is a .NET library for defining, training, and running transformer-style language models. Give it a vocabulary and a shape, train it on your own token sequences through a data-parallel pipeline, and run inference (single prediction, full logits, or streaming generation with a KV cache). The problem it solves: most transformer tooling means either binding into a native runtime (ONNX, PyTorch/libtorch, CUDA) or hand-rolling matrix code with no attention research behind it. AlgFormer sits in between: a real, gradient-trained transformer architecture, written entirely in C# as double[] arrays with SIMD, that runs anywhere .NET runs, with no GPU, no Python, and no native binary to ship. It also lets you compare two ideas of what "attention" should cost. Standard softmax attention scores every token against every other token — quadratic in sequence length. AlgFormer ships a second, holographic attention core alongside it that composes context through bind/bundle/unbind operations instead — linear in sequence length, with constant-time-per-token serving. Why it's useful: two real cores (AlgFormer softmax, HoloFormer holographic) sharing the same model shape, training loop, checkpoint format, and serving API; no external ML runtime; attention that scales differently (HoloFormer is O(T·d) to train, effectively O(1) per token to serve, versus O(T²·d) for standard attention); a subword tokenizer, data-parallel trainer, streaming generation with a KV cache, checkpoint save/load with format versioning, and helpers to grow a trained model to a longer context or bigger vocabulary; distributed/swarm training over MQTT. Check the live NuGet listing (EvaluatedApplications.AlgFormer) for the exact current version. Minimal example: ```csharp using PrismFormer; var model = new AlgFormer(vocab: 16, shifts: 4, layers: 2, maxContext: 6, dModel: 32, frozenPrefix: 0); var data = new List<(int[] Ctx, int Target)> { (new[] { 1, 2, 3 }, 4), (new[] { 2, 3, 4 }, 5), }; var trainer = new PrismTrainer(model); // data-parallel via EvalApp double loss = trainer.TrainEpoch(data, batchSize: 2, lr: 5e-2, shuffleSeed: 1); var context = new[] { 1, 2, 3 }; int next = model.Predict(context); double[] logits = model.LogitsFor(context); int[] generated = model.Generate(context, maxNewTokens: 5, temperature: 0.8, seed: 1); ``` Swapping in the holographic core is the same shape — construct a HoloFormer instead of an AlgFormer with matching dimensions. Compatibility: .NET 8 and .NET 10, pure managed code, no native dependencies. Depends on the Phasor codec package and the EvalApp pipeline runtime; swarm relay components use MQTTnet. License: proprietary, compiled library only — evaluation and non-commercial use are permitted; commercial use requires a commercial licence; no feature is gated in code. ================================================================================ # AlgFormer.Gpu — EvaluatedApplications.AlgFormer.Gpu Page: https://evaluatedapplications.github.io/algformer-gpu.html Install: dotnet add package EvaluatedApplications.AlgFormer.Gpu ================================================================================ Optional GPU acceleration for AlgFormer's HoloFormer engine — same model, same weights, just faster. What it does: AlgFormer.Gpu adds ILGPU/CUDA-backed training and inference for the HoloFormer (resonator/holographic attention) engine from the core AlgFormer package. It builds GPU kernels straight from a CPU HoloFormer's serialized weights — no separate model format, no retraining to switch devices. Backward passes, the fused on-device Adam optimizer step, and batched forward inference all run on the GPU when one is present, with the CPU engine automatically taking over when it isn't. Why it's useful: drop-in, not a rewrite (point it at an existing CPU HoloFormer, it trains/serves against the same serialized weights); automatic fallback (the same build works on a machine with a CUDA GPU and one without); correctness-checked against the CPU engine (every GPU kernel is gradient-checked against the CPU HoloFormer's double-precision math as the reference oracle — GPU runs in float32 for speed, so results are float-close, not bit-identical); fused on-device Adam avoiding a CPU round trip on every training batch. Check the live NuGet listing (EvaluatedApplications.AlgFormer.Gpu) for the exact current version. Key features: GPU-batched forward and backward training for HoloFormer, including per-layer weight-tied iterative refinement ("StackIter") and all-positions loss; fused on-device Adam optimizer step plus checkpoint/resume of the GPU-resident optimizer state; automatic device detection (GpuDevice.HasGpu) with silent, safe CPU fallback; standalone kernel verification utilities. Good to know: requires an ILGPU-supported CUDA device at runtime to actually use the GPU path, otherwise falls back to CPU automatically. Optional — the core AlgFormer package has no GPU dependency at all and stays dependency-free and AOT/trim-safe. Also includes GPU support for AlgFormer's earlier (non-HoloFormer) softmax-attention model, which is deprecated — new projects should use the HoloFormer path. Requires the core EvaluatedApplications.AlgFormer package alongside it. NOTE: this package's owner-authored site.md does not include a minimal code sample; none is invented here. See the API description above and the package's own CLAUDE.md for exact call shapes, or ask the package owner for one. ================================================================================ # Prism — EvaluatedApplications.Prism Page: https://evaluatedapplications.github.io/prism-package.html Install: dotnet add package EvaluatedApplications.Prism ================================================================================ The AlgFormer/HoloFormer production standard: a stamped, append-only lineage journal that answers "what was true when this happened" without ever re-deriving history from current state, plus the canonical confidence-gated decode policy a real AlgFormer/HoloFormer host runs in production. What it does: Prism packages two things. First, a lineage journal that records every structural change to a growing model — genesis, a context grow, a layer grow, a shift grow, or a runtime knob changing value — stamped with every parameter a later calculation might need, captured at the moment it happened. Second, a canonical decode policy: commit greedily when the model is confident, otherwise sample only from what clears a resonance floor (or, for the non-holographic core, from the whole vocabulary at temperature), plus a guard that catches a decode run collapsing into repetition. Why it's useful: three real production bugs in an AlgFormer/HoloFormer training host shared one root cause — a value re-derived from CURRENT state instead of read from a STAMPED fact about the past. Prism's lineage journal makes that whole category of bug structurally impossible: every derivation walks the stamped event history up to the round in question, never the ambient present. The decode side exists because the confidence-gated sampling logic that ships in production had been hand-copied multiple times across a codebase, with two genuinely different real behaviors never written down as a deliberate choice; Prism names both and ships them as one tested policy. Key features: Lineage.LineageJournal (idempotent append, derivations AlphaAt/DepthAt/ LastGrowthRound/AddRoundOf that always resolve against stamped history, including front-insert layer growth); Lineage.ILineageStore (FileLineageStore, JSONL durable append, and MemoryLineageStore for a browser/WASM host with no filesystem); Growth.Grow (a growth surface over HoloFormer — context/layers/shifts/vocab — correct by construction, stamps the journal automatically); Inference.DecodePolicy/Gate/GateDecision (the confidence-gated decode with an explicit FloorMode: a resonance-sigma floor, no floor, or nucleus top-p sampling); Inference. DegenGuard (fires on either a repeat run or a non-greedy-picks run). Good to know: depends on EvaluatedApplications.AlgFormer only (resolved automatically). Namespaces: Prism.Lineage, Prism.Inference, Prism.Growth. Consumed in production by two real hosts — an internal training host routes decode through Gate (30,400 parity checks against the pre-migration hand-rolled logic, zero mismatches), and this site's own browser-side tools consume Prism.Inference by NuGet, never a source reference. License: proprietary, compiled library only — evaluation and non-commercial use are permitted; commercial use requires a commercial licence; no feature is gated behind a tier or a license key. Check the live NuGet listing (EvaluatedApplications.Prism) for the exact current version. NOTE: "Prism" is also the name of a separate, unrelated live chat demo under /tools/prism/ (a Showroom tool powered by the AlgFormer package, not this one) — don't conflate the two. ================================================================================ # HoloDb — EvaluatedApplications.HoloDb Page: https://evaluatedapplications.github.io/holodb/ Install: dotnet add package EvaluatedApplications.HoloDb ================================================================================ **One store. Query it by key, by content, or by aggregate.** ## What it is HoloDb is an embeddable SQL database for .NET with ACID transactions, similarity search (NEAREST) and maintained aggregates. We built it to answer key lookup, similarity search, and aggregation against one copy of the data instead of three different systems. It stores data as **holograms** in a single associative store. Every value is encoded as a phase vector, and a row's columns are bound into one hologram, so the same copy of the data can be retrieved three ways: exact lookup by primary key (ordinary SQL), similarity search by content (`NEAREST`), and constant-time analytics that read a maintained total instead of scanning. Most databases bolt a separate vector index and a separate analytical cube onto a row store and keep all three in sync. HoloDb keeps one copy and answers all three kinds of question against it. ## The problem it solves Applications that need relational storage, similarity/vector search, and fast dashboard rollups normally reach for three different systems, a row store, a vector index, and either a cube or a pile of scans, and pay the integration cost of keeping them consistent. HoloDb collapses that into one embeddable .NET package with real ACID guarantees, so a single `dotnet add package` gets you a transactional store, an in-SQL similarity search, and aggregates whose response time doesn't grow with the table. ## Why it's useful - **No separate vector index.** `SELECT … FROM t NEAREST (col=val, …) LIMIT k` ranks rows by resemblance to a partial description, in SQL, over the same rows the table already holds, gradedly: a close number/date or a near-identical string ranks ahead of a far/unrelated one, and the ranking score itself is readable as a `score` pseudo-column. - **Parameterized queries.** Every `Execute` has a `?`-placeholder overload (ADO.NET-style positional binding, correctly quoted/escaped) alongside the raw-SQL-string form. - **Aggregates don't scan.** An integer column's running total is itself one maintained vector, so whole-table `COUNT`/`SUM`/`MIN`/`MAX` and single-column `GROUP BY` read that value directly, constant time, flat as the table grows from a thousand rows to tens of millions. - **Real ACID, not a toy.** Write-ahead logging (a durable database flushes each commit to disk with fsync before it returns), crash recovery bounded by live data (not the full write history), reader/writer locking, and atomic statements. - **Survives partial loss by design.** Columns are the source of truth; holograms are always derivable from them, never the other way around, the store degrades gracefully rather than silently, since the authoritative data was never only in the hologram. - **Scales past RAM.** Paged tables (8 KB pages in a buffer pool, plus a write-ahead log) let a table exceed memory, with demand-paging and the same maintained aggregates kept accurate on disk. A paged table's primary-key index stays in RAM, at about 35 bytes per row (measured: 39 and 34 bytes per entry for a 1,000,000 and a 10,000,000 entry map). - **Dashboard reads during live ingest.** Whole-table counts and sums, and GROUP BY on a column with up to 64 distinct values, are served from a snapshot republished after every write, without taking the engine's write lock. Measured (EXP-PB10, one run: 2,000,000 events in 1,000-row batches at 1.16 million events a second, 4 concurrent readers): median read 0.009 to 0.09 ms, p99 0.8 ms (group by region), 1.1 ms (sum) and 6.6 ms (count), worst single read 6.7 ms. A GROUP BY with more than 64 distinct values (the per-minute series in the same test has 167) takes the normal locked path and waited behind the ingest for up to 0.9 s (p99 0.9 s). ## Where the plane is the right tool The optional Pleroma aggregate plane (described under "Built on Pleroma" below) pays off on three kinds of workload, and it has costs that sit next to the wins. These workloads were constructed to suit the plane and are measured separately from the engine-only comparisons below, which do not use it. These figures are the EXP-PS1 plane showcase, one run on one machine on 13 October 2026 on the build released as 5.1.1: an 11th Gen Intel Core i9-11950H at 2.60 GHz (16 logical cores), 18.1 GB of 31.7 GB memory free at the start, no other .NET process running, with ordinary desktop applications and the SQL Server service open, so this is not an idle-machine run. Every HoloDb figure is an in-memory database with no write-ahead log; SQLite and DuckDB ran in memory and SQL Server LocalDB used tempdb on disk. Each cell is the median of the lower of two timing loops; the per-round figures in B are medians over rounds. Every timed query returned identical results on all engines, and after each workload `PleromaVerify` found the plane equal to a rebuild from the columns. "Engine" is HoloDb without a plane, "plane" is HoloDb with the plane attached and default routing, both embedded. What the three workloads have in common: the filter combinations cannot be pre-indexed because nobody knows in advance which dimensions a person will cut by, the answers must be exact, and the table keeps changing while it is queried. ### A. A live dashboard: 10,000,000 events, 32 ad-hoc slices Six small-domain dimensions (a 14-bit joint) and the measures. Building the plane for 10,000,000 rows took 1,759 ms and its cells take 920,248 bytes. The 32 slices are scalar filters (W), group-bys with and without a filter (G), HAVING (H), COUNT DISTINCT and MIN/MAX with a filter (D), plus queries outside the plane (X) and whole-table queries the engine already answers from a maintained total (S). | Class (queries) | Plane vs engine, median | Plane vs best of SQLite, DuckDB, SQL Server, median | |---|---|---| | W scalar slices (9) | 121.40x | 191.5x | | G group by (7) | 20.90x | 27.4x | | H having (2) | 24.57x | 42.2x | | D distinct, min/max with a filter (3) | 18.42x | 36.0x | | X outside the plane (7) | 0.97x (tie) | 1.5x | The best other engine on the W, G, H and D slices is DuckDB in every row shown. In W, three of the nine cells (A10, A11, A12) are not interpreted because the engine's own two timing loops disagreed by more than 25%; the class median is as printed. **First calls.** The first call of each query, which pays any one-time work, is also faster with the plane: the median first-call speed-up over the engine is 16.99x for W, 10.90x for G, 13.97x for H and 10.17x for D. A04 takes 1.047 ms on its first call with the plane against 17.792 ms for the engine. Across the first four rows below, the plane takes 0.153 to 2.110 ms, the engine 18.526 to 50.189 ms and DuckDB 25.185 to 67.130 ms. | Query | DuckDB | SQL Server | HoloDb engine | HoloDb plane | |---|---|---|---|---| | A04 `WHERE region = 'north' AND device = 'mobile'`, COUNT and SUM | 25.185 | 827.218 | 18.526 | 0.153 | | A13 `GROUP BY region, device`, COUNT and SUM | 56.712 | 3,012.047 | 43.222 | 2.068 | | A19 `GROUP BY region, channel HAVING COUNT(*) > ...` | 67.130 | 3,047.374 | 43.815 | 2.110 | | A22 `COUNT(DISTINCT channel), COUNT(DISTINCT device)` with a WHERE | 37.506 | 2,336.280 | 50.189 | 0.803 | | A25 (outside the plane: filter on `user_id`, a column that is not a dimension) | 12.139 | 486.466 | 11.300 | 11.484 | The queries the plane declines or leaves to the engine (the X class: a filter on a non-dimension column, `COUNT(DISTINCT user_id)`, a sum of a non-measure column, a top-10 by user, a filter on a measure, a row list and a point lookup by event id) run the engine's own path with the plane attached and tie with the engine: the seven X queries read 0.95x to 1.04x warm. The plane arm is ahead of the best other engine on them by 1.1x to 3.3x; A25, A28 and A31 are ahead by only 1.1x, and the 3.3x is the point lookup (0.002 ms against SQLite's 0.007 ms). On the first call, five of the seven (A25, A27, A28, A30, A31) were slower with the plane attached, at 0.42x to 0.84x of the engine's first call; these are single samples, and the warm ratios are 0.95x to 1.04x. ### B. Live ingest while querying A 2,000,000-row base table, then 20 rounds of a 10,000-row bulk load, 200 single-row INSERTs and an eight-query dashboard panel, then 300 trickle pairs (one INSERT followed by one group-by query). The panel's results matched in every round. Per round, medians: | Per round (ms) | SQLite | DuckDB | SQL Server | HoloDb engine | HoloDb plane | |---|---|---|---|---|---| | panel (8 queries) | 3,794.93 | 112.30 | 3,057.90 | 137.90 | 11.53 | | round total (bulk load, INSERTs, panel) | 3,816.72 | 239.88 | 3,109.90 | 149.47 | 25.84 | | trickle pair (INSERT plus query) | 760.784 | 16.088 | 419.610 | 7.634 | 1.090 | The plane makes the panel 11.95x faster than the engine and the round total 5.78x faster; the trickle pair is 7.00x faster. Through the server the round total is 179.34 ms for the engine and 45.65 ms with the plane. **What the plane costs on the write side:** the 10,000-row bulk load takes 11.62 ms against 9.85 ms (1.18x), and 200 single-row INSERTs take 1.55 ms against 1.23 ms (1.26x), about 7.8 microseconds against 6.2 per INSERT. The first panel query after each ingest (P1, the A04 shape) gains only 1.66x (2.304 ms against 3.835 ms), while the other seven gain 2.87x to 319.60x. The likely cause is the flush of the plane's pending changes that the first query after an ingest triggers; the flush was not timed separately. DuckDB takes 6.288 ms on that query, so the plane is still ahead of it (2.7x), and on the others the plane takes 0.202 to 2.082 ms against DuckDB's 5.147 to 28.316 ms. ### C. Multi-tenant: slices and joins Five million events spread over six tenant tables (2,000,000 down to 150,000 rows) and a 2,000-product dimension table. **Tenant slices.** A filter and a COUNT and SUM on one tenant (C0c to C5c): median 11.70x faster than the engine and 25.0x faster than the best other engine. The largest tenant reads 0.171 ms with the plane, 4.263 ms for the engine, 6.312 ms for DuckDB and 195.195 ms for SQL Server. The C2c cell is not interpreted (its two timing loops on the HoloDb arms disagreed by more than 25%); the medians are as printed. **Joins, stated exactly.** The join in these tests is the same statement repeated: tenant events joined to the products table on the product key (about 2,000 keys), with `COUNT(*)` alone (a) or `COUNT(*)` and two `SUM`s (b). The plane serves a repeat from a memo of the exact answer, which by design (and by the `joincache` checks, not by this run) is valid until either of the two tables is written. So the very low figures below are for a repeated identical statement with no write in between: | Query | DuckDB | SQL Server | HoloDb engine | HoloDb plane, embedded | HoloDb plane, server | |---|---|---|---|---|---| | C0a join COUNT, largest tenant (2,000,000 rows) | 1.749 | 307.039 | 0.380 | 0.002 | 0.078 | | C0b join COUNT and two SUMs, largest tenant | 2.906 | 477.043 | 2.716 | 0.003 | 0.079 | | C5a join COUNT, smallest tenant (150,000 rows) | 0.947 | 23.678 | 0.110 | 0.002 | 0.071 | | C5b join COUNT and two SUMs, smallest tenant | 1.392 | 37.158 | 0.999 | 0.003 | 0.073 | Embedded, a memo hit takes 0.001 to 0.003 ms; through the server it takes 0.071 to 0.084 ms, against DuckDB's 0.947 to 2.906 ms and the engine's 0.110 to 2.716 ms for the same joins. A join that is not a memo hit usually costs more than the engine's own join. **The first call of a statement costs more through the plane than through the engine in 11 of the 12 join cells.** A call after a write to either table was not timed in this run; by design it runs the same computation as a first call, but a first call also pays one-time costs, so treat the first-call figures below as indicative of it, not as a measurement. First calls in this run: join COUNT 1.016 to 2.921 ms through the plane on the five later tenants (1.372, 1.088, 2.921, 1.016, 1.245 ms) against 0.179 to 0.573 ms for the engine; the first join of the whole run, which also pays one-time start-up, was the one cell where the plane was lower: 13.800 ms against the engine's 18.540 ms. Join COUNT and two SUMs 2.348 to 8.134 ms through the plane (8.134, 6.230, 3.138, 2.610, 4.498, 2.348 ms) against 1.364 to 3.076 ms for the engine. If the tables are written between nearly every read, expect the plane join to cost more than the engine's own join, and the plane's value on such a workload to come from the filters and group-bys above, not the joins. Joins with a WHERE or a GROUP BY on the dimension table are not served by the plane at all; they run the engine's path and tie with it (C-X1 to C-X4, 0.93x to 1.02x). ### The checks that guard these figures Queries the plane declines or leaves to the engine moved within noise: of the 16 queries that run the same path in both arms, none fell outside the registered band of 0.8x to 1.25x, and the class medians were 0.97 (workload A) and 0.99 (workload C). A placebo built to catch a wrong plane (the measure column shuffled at 1,000,000 rows) was caught on every query it was registered to change and matched on every query it was registered not to change: 0 failures of 32. `PleromaVerify` found the plane identical to a rebuild from the columns after each workload. ## Built on Pleroma HoloDb 5.1.1 is built with Pleroma, the exact count-and-sum structure in the Phasor package. Three parts of HoloDb are Pleroma parts, and this section says what each gives you today and what it costs. The first two are optional and off until you ask for them. **The headline results are the engine's, not the plane's.** The 10,000,000-invoice billing comparison against SQLite, DuckDB and SQL Server (EXP-PB12), and the single-row write tables against SQLite, were run on the HoloDb engine alone, with no Pleroma plane attached. All HoloDb figures on this page come from in-memory databases with no write-ahead log. The plane is a separate, opt-in feature, measured in its own runs below, and it was not on in those comparisons. ### The aggregate plane: exact answers from a derived summary You name a few small-domain columns (dimensions, INT or TEXT) and the INT columns to sum (measures). HoloDb keeps a Pleroma summary of them, updated by every write, and answers filters, multi-column GROUP BY, `COUNT(DISTINCT)`, MIN/MAX of a dimension and equi-join COUNT and SUM from it, without scanning the table. - **Exact and derived.** The columns stay the source of truth; the plane is rebuilt from them. `PleromaVerify` rebuilds it and compares, and returns nothing when they agree. Sums are held exactly past 64 bits: the plane raises an error rather than wrap, and `PleromaSumExact` returns the exact 128-bit total. - **It declines safely.** Anything the plane does not hold (AVG, a column that is not a dimension or measure, a dimension over its cap of distinct values, a join over 4,095 keys) goes to the engine, so a query returns the same rows with the plane on or off. The default routing, `PleromaMode.Auto`, also leaves to the engine the shapes where the engine already reads a maintained total (whole-table counts and sums, single-column GROUP BY) and GROUP BY with a WHERE below 140,000 rows, because the engine is faster there. - **Measured on the billing workload (EXP-PB11, 10,000,000 invoices, plane on `region`, `status`, `month` and the measure `amount_cents`).** Building the plane took 741 ms and its cells take 34,528 bytes. "Overdue outstanding" went from 5.93 ms to 0.01 ms, and "revenue by region and status" from 32.30 ms to 0.18 ms. All 16 results were identical across all engines. Per database the plane served 12 calls (overdue outstanding and region and status, six calls each) and declined 42 (seven queries, six calls each): the big-ticket count (the filter is on a measure), top customers (200,000 distinct customer ids against a cap of 1,024) and all five joins (200,000 join keys against a limit of 4,095). The five rollups were left to the engine by the default routing, and the lookup and largest-invoices queries have no aggregate to serve. Cells the plane does not touch moved by up to 33 percent between the two columns, which is noise. - **What it costs, stated plainly.** At 1,000,000 rows (17 query classes) the plane is slower than the engine alone on 4 of them: whole-table `COUNT(*)` (0.48x), whole-table `SUM` (0.47x), single-column GROUP BY (0.43x) and MIN/MAX (0.53x), because the engine reads a maintained total in microseconds there; it ties on 3 and is not interpreted on 2 (noise). It is faster on 8: on 7 by at least 3.0x (COUNT DISTINCT with a WHERE) up to 4,670x (the TEXT-key join, which has 4 distinct join keys), and on GROUP BY with a WHERE by 1.34x. At 100,000 rows the engine is faster on 7 of the 17 classes. Single-row INSERT costs 1.4x to 1.9x more with a plane attached and UPDATE 1.6x to 1.8x (100,000 to 1,000,000 rows); these cells are microseconds and move with arm order. - **Limits.** Memory-resident tables only (a paged table refuses a plane; a database opened with a log is still durable). A plane attached with `EnablePleroma` is not persisted: call it again after `Open`. A plane created with SQL is replayed from the log and survives `Checkpoint()`. Opt-in per table. ### Index SQL and EXPLAIN: build it and see why The plane has a SQL form, so a remote client can build it through the server like any statement. `SHOW INDEXES` reports its size and how many queries it served and declined, and `EXPLAIN` reports why a query was served or declined, without running it. ```csharp using HoloDb; var db = Database.Open(); db.Execute("CREATE TABLE sales (id INT PRIMARY KEY, region TEXT, tier INT, qty INT)"); db.Execute("INSERT INTO sales (id, region, tier, qty) VALUES (1,'north',1,10),(2,'north',2,-4),(3,'south',1,7),(4,'east',3,5),(5,'south',2,9)"); // build the plane from SQL: key columns are dimensions, INCLUDE columns are measures db.Execute("CREATE INDEX by_region ON sales (region, tier) INCLUDE (qty) USING SUMMARY"); db.PleromaMode = PleromaMode.Always; Console.WriteLine(db.Execute("SELECT SUM(qty) FROM sales WHERE region = 'north' OR tier = 3").Rows[0]["sum(qty)"]); // 11 // why was it served, or declined? foreach (var r in db.Execute("EXPLAIN SELECT region, SUM(qty) FROM sales WHERE region = 'north' GROUP BY region").Rows) Console.WriteLine($"{r["kind"]}: {r["route"]}"); // route: Pleroma plane (exact aggregate from the derived plane) foreach (var r in db.Execute("EXPLAIN SELECT COUNT(*) FROM sales WHERE qty > 5").Rows) Console.WriteLine($"{r["kind"]}: {r["route"]}"); // decline: WHERE uses a column that is not a plane dimension, a dimension over its cap, a column-to-column comparison or a subquery // access: block-wise mask scan // route: predicate count (block-wise byte-mask, no position list) Console.WriteLine(db.PleromaVerify("sales") ?? "plane equals a rebuild from the columns"); // plane equals a rebuild from the columns Console.WriteLine(db.PleromaSumExact("SELECT SUM(qty) FROM sales")); // 27 ``` `EXPLAIN` runs the engine's own routing code in a mode that stops before the heavy work, so what it reports is the decision the real statement takes. It does not run an `IN (SELECT ...)` subquery (it is shown unresolved). Older binaries cannot open a log or snapshot that contains this SQL. A checkpoint on 5.1.0 produces a file an older binary can read only if no table has a named index or SQL-created plane. ### The Pleroma page store: durable, checksummed pages `PleromaPageStore` holds many exact Pleroma pages as the data itself, durably and larger than memory, with no columns behind them. `PleromaSparsePageStore` does the same for sparse pages over a large vocabulary. - **Checksummed pages.** Every page carries a check prime (a mirror of its cells in a second prime) and a header hash. `Verify` proves every record and parity group intact; `VerifyOnLoad` does the same on every load and is off by default (about 100 microseconds for a 110-key page). - **Parity repair.** Records are grouped (8 by default) with one exact-sum parity record per group, and the members of a group sit on different 8 KB pager pages. Any one lost pager page, or any one damaged record per group, is rebuilt by `Repair`. A rebuilt page must pass its own check before it is written; a page and its group's parity both damaged are reported as unrecoverable, never rebuilt wrong. - **Restore points.** `Checkpoint()` returns a restore point and `RestoreTo` returns the store to exactly that state, with no recount. It is copy-on-write, so a restore point costs one before-image per page changed since, not a copy of the data. Eight are kept by default. - **Exactly-once replay.** Every `AddBatch` is journaled (fsynced by default) before it is applied, and each page remembers the last batch applied to it, so crash recovery applies a logged add exactly once, even over pages already flushed. A torn journal tail is discarded, so a batch survives whole or not at all. - **Proof.** 72 of 72 store checks pass (crash replay, torn tail, restore, repair from a parity group); eight deliberate mutations and a tiny-cache case each turned the suite red. ```csharp using HoloDb; using Phasor; var shape = new HologramShape { KeyCapacity = 2, KeyCycle = 110, CompleteKeys = true }; var dir = Path.Combine(Path.GetTempPath(), "plrstore-restore"); if (Directory.Exists(dir)) Directory.Delete(dir, true); using (var store = PleromaPageStore.Open(dir, shape)) { store.AddBatch(new[] { new PageAdd(42, 5, 3) }); var point = store.Checkpoint(); // a restore point: id and journal position store.AddBatch(new[] { new PageAdd(42, 5, 10), new PageAdd(9, 1, 1) }); Console.WriteLine($"{store.Counts(42)[5]} {store.Contains(9)}"); // 13 True store.RestoreTo(point.Id); // back to the point, no recount Console.WriteLine($"{store.Counts(42)[5]} {store.Contains(9)}"); // 3 False Console.WriteLine(store.Verify().Clean); // True Console.WriteLine(store.Repair().Unrecoverable.Count); // 0 } Directory.Delete(dir, true); ``` **Limits.** One shape per store, and it must be `CompleteKeys` and admissible for a check prime; shapes with a continuous component or a relation face cannot be saved. One process opens a store at a time and one writer works at a time. A batch is applied page by page, so a reader sees every page whole but may see a batch on some pages and not yet on others. The sparse store has no parity groups, restore points or event journal yet. Page-store throughput is not reported on this page. ### Opening a database Opening a database of 1,000,000 rows (a 43 MB log) takes about 2.0 s by replaying its write-ahead log (1.95 to 2.05 s across two runs) and about 1.1 s from a checkpoint (1.09 to 1.11 s), with the loaded state checked correct and a heap of about 110 bytes per row. Conditions: in process, a newly started process each time, an idle 16-core machine on 12 October 2026. This is the engine's own recovery and checkpoint; it does not use the plane or the page store. ## Current version HoloDb 5.1.1 (NuGet package `EvaluatedApplications.HoloDb`). The package's own `` in `HoloDb.csproj` is the source of truth for later releases. ## Key features - SQL surface: `CREATE TABLE [IF NOT EXISTS]`/`CREATE INDEX [name] ON t (cols) [INCLUDE (cols)] [USING SORTED | SUMMARY] [WITH (max_dim_bits = n, max_joint_bits = n)]` (`USING SUMMARY` builds the aggregate plane from SQL), `DROP INDEX name`, `SHOW INDEXES [ON t]`, `EXPLAIN SELECT ...` (which route and which index or zone map answers a query, and why a faster one was declined, without running it), `ALTER TABLE ... ADD COLUMN ... DEFAULT ` (add-only, no `DROP`/rename/type-change), `INSERT`/`UPDATE`/`DELETE`, `SELECT` with `DISTINCT`, `COUNT`/`SUM`/`MIN`/`MAX`/`AVG`, a single `INNER JOIN`, `WHERE` (`AND`/`OR`/`NOT`/`LIKE`/`IN`/`BETWEEN`, subquery `IN`), `GROUP BY`/`HAVING`, `ORDER BY`, `LIMIT`, `NEAREST` similarity search, and explicit `BEGIN`/`COMMIT`/`ROLLBACK` transactions. - Columns: `INT`, `TEXT`, `REAL`; primary key is `INT` or `TEXT`/GUID, enforced unique. - Constant-time exact integer aggregates (`COUNT`/`SUM`/`MIN`/`MAX`, single-column `GROUP BY`), exact, not approximate; real-number aggregates use a fast SIMD scan. - Content-addressable `NEAREST` similarity search directly in SQL, no separate index to maintain. From 8,000 rows upward an approximate sublinear index (locality-sensitive hashing) ranks candidates, so the result can differ from an exact scan (its recall is not measured on this page); below that, and whenever the query has a WHERE, ranking is an exact scan, graded closeness for numbers/dates/text, plus a `score` column on request. - Parameterized `Execute(sql, args)` (`?` placeholders) on every entry point, alongside raw SQL text. - Durable, larger-than-memory tables (`CreatePaged`/`OpenPaged`) on a buffer-pool + WAL page store, with primary-key point lookup, a single `INNER JOIN`, `GROUP BY`/`HAVING`, and `NEAREST` all supported on the paged path. - Transactions that stay constant-time: `BEGIN` does not copy the table (rows are journaled as they change and `ROLLBACK` replays the journal), and single-row autocommit statements run in microseconds. - Block-wise column scans: a WHERE is evaluated over raw column arrays in tight loops, GROUP BY over INT and TEXT columns uses dense codes, and an equi-join on TEXT keys is a columnar hash join. - A per-query usage meter (rows/bytes actually processed) for billing or observability. - Embeddable both in-process and as a networked server with a matching typed client. - **Pleroma aggregate plane (optional):** attach an exact, derived plane to chosen small-domain columns with `EnablePleroma`. Writes keep per-column shadows current, and the plane answers WHERE aggregates over any AND/OR/NOT/LIKE/IN/BETWEEN predicate, multi-column GROUP BY, `COUNT(DISTINCT col)`, MIN/MAX and equi-join COUNT/SUM from Phasor Pleroma stores, with signed sums held exactly past 64 bits. Anything outside the plane's columns or caps is answered by the engine, so results never differ. The columns remain the source of truth; the plane is rebuilt from them in batch. - **Pleroma page store (optional):** ``PleromaPageStore`` holds many exact Phasor Pleroma pages as the data itself, durably and larger than memory, and ``PleromaSparsePageStore`` does the same for sparse large-vocabulary pages. Readers do not block on a writer working on other pages, adds are journaled before they are applied and replay exactly once after a crash, restore points rewind the store to a journal position without recounting, an opaque event journal shares the same order, and every page carries a Phasor check prime plus parity groups so ``Repair`` can rebuild a lost or corrupted page. ## Measured Every figure below is **one run on one machine** (16 cores, AC power, idle, no other benchmark or heavy application running; the runs are dated 12 October 2026) and carries its experiment id. Outcome thresholds and noise tests were written down before each run, every timed query first had to return identical rows from SQLite and from HoloDb (the billing workload from all five engines), and a cell whose own two timing loops disagreed by more than 25% is marked as not interpreted. **SQLite** (in-memory, the external reference) is always listed first. In the plane benchmark the **HoloDb engine** is the same database without a plane (its own maintained totals, zone maps and block-wise column scans) and the **HoloDb plane** is a database with the optional Pleroma plane attached. Times are medians of repeated calls. "Fresh process" means the first statements of a newly started process, which is what an application feels after it starts; the cost of just-in-time compilation is included. **What ran with logging and what ran in memory.** Every HoloDb figure on this page (embedded, server, engine alone, plane) is an in-memory database opened with no file path (`Database.Open(null)`): no write-ahead log and no fsync. SQLite and DuckDB ran in memory (`:memory:`). SQL Server 2022 LocalDB ran with its tables in `tempdb` on disk (data and log files, logged by tempdb's rules, not kept across a restart). So the single-row write tables compare the engine alone against in-memory SQLite and do not measure durable commits: a HoloDb database opened with a write-ahead log appends each committed statement and flushes it to disk (fsync) before returning, which costs one fsync per commit on top of these figures, set by the disk and not measured here. The bulk-load rates compare unlike modes: HoloDb typed arrays into memory (the server one over TLS), DuckDB's appender into memory, SQLite inserts in one transaction into memory, and SQL Server's bulk copy into tempdb on disk. ### Billing workload: HoloDb against SQLite, DuckDB and SQL Server (EXP-PB12, 10,000,000 invoices) **The workload.** A billing SaaS's invoice ledger, the shape of data a subscription business runs its dashboards on: a normalised `invoices` fact joined to a `customers` dimension. ``` CREATE TABLE customers ( customer_id INT PRIMARY KEY, -- 200,000 customers name TEXT, segment TEXT, -- smb / mid / enterprise / strategic tier TEXT, -- gold / silver / bronze signup_month INT ); CREATE TABLE invoices ( invoice_id INT PRIMARY KEY, -- 10,000,000 invoices customer_id INT, -- foreign key to customers, about 50 invoices each month INT, -- yyyymm, 202301 to 202412 (24 months) region TEXT, -- US 40% / EU 30% / APAC 20% / LATAM 10% status TEXT, -- paid 78 / pending 10 / overdue 7 / refunded 3 / failed 2 (%) amount_cents INT ); -- money as integer minor units (cents), long tail $20 to $50,000 ``` **The method.** The same data (fixed seed) and the same SQL on five engines, each loaded through its own bulk path: **SQLite** (in-memory), **DuckDB** (in-process, in memory, its fastest mode), **SQL Server 2022 LocalDB** (on disk, in tempdb), **HoloDb embedded** (in-process) and **HoloDb server** (networked over TLS on the loopback interface, the fair peer to SQL Server's client/server round trip). Sixteen queries a billing business actually runs: five rollups (revenue by status, month and region, the total, the count), a single-invoice lookup, five single-table scans (overdue outstanding, big-ticket count, largest invoices, top customers, a region and status breakdown) and five cross-table joins to the customer dimension (revenue by segment, by segment and status, enterprise revenue, by signup cohort, top named customers). **Before any query is timed, its full result set is normalised and compared across all five engines; every one of the 16 results was identical.** Times are the median of 5 runs of execute plus consume-every-row through each engine's typed client API, on a 16-core machine on 12 October 2026, started at 10 percent CPU with 17.4 GB of memory free and no other benchmark or heavy application running. It is **one run on one machine**, and it is the final run of this comparison: it supersedes the two earlier runs of the same benchmark on the same machine the same day (EXP-PB7 and EXP-PB9), against which it agrees on every engine's unchanged cells (the DuckDB and SQL Server medians are about 7 percent higher in this run). Bulk load, rows per second: DuckDB 1,159,279; HoloDb server 1,051,473; SQLite 726,050; SQL Server 693,231; HoloDb embedded 679,271. **In-process, in memory: HoloDb embedded against DuckDB (and SQLite), median ms** | Billing query | SQLite | DuckDB | HoloDb embedded | Faster | |---|---|---|---|---| | invoices by status | 3,719.66 | 41.63 | 0.02 | HoloDb, more than 1,600x vs DuckDB | | revenue by region | 3,492.70 | 34.33 | 0.02 | HoloDb, more than 1,300x | | total invoiced | 414.54 | 2.56 | 0.00 | HoloDb, more than 510x | | revenue by month | 3,584.01 | 5.48 | 0.04 | HoloDb, more than 120x | | invoice count | 13.90 | 0.68 | 0.00 | HoloDb, more than 130x | | look up one invoice | 0.01 | 0.60 | 0.02 | SQLite ahead, 0.01 ms | | revenue by segment (JOIN) | 6,527.97 | 49.01 | 14.71 | HoloDb 3.3x | | top named customers (JOIN) | 8,944.31 | 291.33 | 132.35 | HoloDb 2.2x | | revenue by segment and status (JOIN) | 10,685.41 | 77.54 | 36.17 | HoloDb 2.1x | | overdue outstanding | 440.80 | 11.93 | 6.12 | HoloDb 1.9x | | revenue by region and status | 7,495.52 | 58.09 | 35.58 | HoloDb 1.6x | | top customers by revenue | 4,346.30 | 129.61 | 89.87 | HoloDb 1.4x | | largest invoices | 573.94 | 3.28 | 2.42 | HoloDb 1.4x | | big-ticket invoices (over $5k) | 382.92 | 2.57 | 2.49 | tie (1.03x) | | enterprise revenue (JOIN) | 3,047.43 | 8.68 | 8.97 | tie (DuckDB 1.03x) | | revenue by signup cohort (JOIN) | 6,469.16 | 11.96 | 14.92 | DuckDB 1.25x | HoloDb embedded is faster than SQLite on 15 of the 16 queries, from 48x (top customers by revenue) to more than 2,700x on the rollups, and SQLite is ahead on the single-invoice lookup (0.01 ms against 0.02 ms at the benchmark's two-decimal resolution). Against DuckDB, counting a difference under 1.15x as a tie, HoloDb is faster on 13 queries, tied on 2 and slower on 1. The five rollups and the lookup read a maintained total or the primary-key index, so they take microseconds and do not grow with the ledger (the benchmark prints two decimals, so these cells are shown at that resolution and the ratios are lower bounds). **Where HoloDb lost:** the signup-cohort join, 1.25x behind DuckDB (a parallel scan of the 10 million invoices at about 80 ns per row per core against DuckDB's columnar engine), and the single-row lookup against SQLite. **Networked: HoloDb server against SQL Server 2022 LocalDB (and SQLite), median ms** | Billing query | SQLite | SQL Server | HoloDb server | Faster | |---|---|---|---|---| | revenue by region | 3,492.70 | 2,088.59 | 0.19 | HoloDb, about 11,000x | | invoices by status | 3,719.66 | 2,178.58 | 0.20 | HoloDb, about 10,900x | | revenue by month | 3,584.01 | 1,485.33 | 0.35 | HoloDb, about 4,200x | | total invoiced | 414.54 | 943.63 | 0.25 | HoloDb, about 3,800x | | invoice count | 13.90 | 470.33 | 0.17 | HoloDb, about 2,800x | | largest invoices | 573.94 | 1,472.47 | 2.74 | HoloDb, about 540x | | revenue by signup cohort (JOIN) | 6,469.16 | 2,562.84 | 13.88 | HoloDb, about 185x | | enterprise revenue (JOIN) | 3,047.43 | 1,550.70 | 8.55 | HoloDb, about 180x | | revenue by segment (JOIN) | 6,527.97 | 2,626.84 | 14.65 | HoloDb, about 180x | | revenue by segment and status (JOIN) | 10,685.41 | 5,089.70 | 34.35 | HoloDb, about 150x | | big-ticket invoices (over $5k) | 382.92 | 397.23 | 3.06 | HoloDb, about 130x | | overdue outstanding | 440.80 | 588.61 | 5.97 | HoloDb, about 100x | | revenue by region and status | 7,495.52 | 2,792.44 | 34.46 | HoloDb, about 81x | | top customers by revenue | 4,346.30 | 2,426.10 | 87.17 | HoloDb, about 28x | | top named customers (JOIN) | 8,944.31 | 2,616.03 | 127.51 | HoloDb, about 21x | | look up one invoice | 0.01 | 0.07 | 0.18 | **SQL Server, 2.6x** | Both are networked services paying a client/server round trip; HoloDb serves its working set from RAM and SQL Server reads its on-disk table. HoloDb server is faster than SQL Server on 15 of the 16 queries (including all five joins, by 21x to 185x), ties on none and is slower on the single-row lookup, where SQL Server answers in 0.07 ms and HoloDb server in 0.18 ms (SQLite, in the same process as its caller, takes 0.01 ms). The server figures are the median of five calls each, so they include the first-call cost of the network path: a separate longer loop through the same client measured the rollups and the lookup at a steady 0.06 to 0.10 ms (a point query pays a fixed 0.07 ms of client, TLS, socket and result encoding; the same query takes 1 to 3 us embedded), and five-call medians in fresh processes read 0.17 to 0.26 ms (median over eight fresh processes per query; single processes 0.11 to 0.34 ms). **Highlights from this run.** - Total invoiced across 10,000,000 invoices (`SELECT SUM(amount_cents)`), same query, same data, all results identical: SQLite 414.54 ms, DuckDB 2.56 ms, SQL Server 943.63 ms, **HoloDb under 0.01 ms** (a maintained total is read, not 10 million rows). - The five rollups and the single-invoice lookup resolve in microseconds in the embedded engine, and in 0.17 to 0.35 ms as a network service. - As a networked service HoloDb is faster than SQL Server on 15 of 16 billing queries, including every join. - On the five joins the embedded engine is faster than DuckDB on revenue by segment (3.3x), top named customers (2.2x) and segment and status (2.1x), ties it on enterprise revenue, and is 1.25x behind on the signup-cohort join. ### Release check (EXP-PB13) Before 5.1.0 shipped, every benchmark cell was run twice on the release build, back to back on an idle 16-core machine: the 10-million-invoice comparison, the plane benchmark at 100,000, 300,000 and 1,000,000 rows, single-row writes and transactions, and opening a 1,000,000-row database from its log and from a checkpoint. The join count on a 100,000-row table joined to a 40-row table takes about 0.07 ms. ### The optional Pleroma plane on the billing workload (EXP-PB11) The plane is **not on in the comparison above**: it is opt-in per table (`EnablePleroma` with explicit options). This section is a separate run of the same workload (10,000,000 invoices, all 16 results again identical across all engines) with a plane attached to the `invoices` table: dimensions region (4 values), status (5) and month (24), a 10-bit joint, and the measure `amount_cents`. It takes 34,528 bytes of plane cells (+0.3 MB of heap) and 741 ms to build for 10 million rows (749 ms on the server's database). The same database is timed with the plane off and with the plane on (default routing), so every other column of the run is unchanged. | Query | SQLite | DuckDB | HoloDb, plane off | HoloDb, plane on | Plane vs off | |---|---|---|---|---|---| | overdue outstanding | 429.30 | 11.43 | 5.93 | 0.01 | about 600x faster | | revenue by region and status | 7,381.34 | 56.66 | 32.30 | 0.18 | about 180x faster | Through the server the same two queries take 6.30 ms and 34.58 ms with the plane off and 0.11 ms and 0.45 ms with it on (SQL Server: 611.59 ms and 2,898.13 ms). **What the plane serves:** filters and multi-column GROUP BY over its dimension columns. **What it declines, and why:** the big-ticket count (the filter is on a measure, not a dimension), top customers (200,000 distinct customer ids, far over the 1,024-value dimension cap), the five joins (200,000 join keys against a limit of 4,095, and no plane on the customers table), and the lookup and largest-invoices queries (no aggregate). The five rollups are left to the engine on purpose: it reads a maintained total there in microseconds, and the plane is slower. Per database, 12 calls were plane-served (two queries, six calls each) and 42 declined (seven queries, six calls each), exactly the split above. **Noise:** the cells the plane does not touch run the identical engine path in both columns, and they differed by 1 to 13 percent typically and by up to 33 percent (big-ticket: 3.01 ms off, 2.26 ms on), so differences of that size are noise. The server rollups read 0.12 to 0.32 ms off and 0.14 to 0.17 ms on, which is consistent with the first-timed column of each query paying the cold first calls of the network path; the plane does not serve these queries. ### Exactness (Pleroma plane and page store) Proven by checked-in verbs in `HoloDb.Bench` (`pleromaparity`, `pleromastore`, and the engine suites listed under each result). - **Exact, not approximate.** The aggregate plane returns row-for-row the same answers as the engine and SQLite across the parity suite (2,853 checks at 2,000 rows; the suite also passes at 5,000 and 100,000 rows), including a random insert, update, delete, rollback and reopen log, and sums past 64 bits. Nine deliberate mutations (a dropped carry, a missed delete, a stale join limb and others) each turned the suite red. - **Sums past 64 bits are never wrapped.** The plane raises an error and `PleromaSumExact` returns the exact 128-bit total. - **The page store survives faults.** 72 of 72 store checks pass: exactly-once replay after a crash, torn journal tail discarded, restore points that rewind without recounting, and repair of a lost page from its parity group. Eight deliberate mutations and a tiny-cache case each turned the suite red. - **Plane memory is flat.** The cells of a 14-bit joint plane are about 0.92 MB whatever the row count (920,248 bytes at 10,000,000 rows, 922,936 at 100,000 to 1,000,000), plus the same again in pending deltas before a flush. ### Single-row writes and transactions, engine alone against SQLite (EXP-PB4, EXP-PB5) Autocommit statements on a table of the benchmark shape (9 columns), 205 statements per cell, the first 5 dropped, median. EXP-PB5 part C, fresh process (each size in its own newly started process): | Statement | Rows | SQLite | HoloDb engine | Engine vs SQLite | |---|---|---|---|---| | single-row INSERT | 100,000 | 5.2 us | 7.7 us | 1.5x | | single-row INSERT | 1,000,000 | 4.3 us | 7.0 us | 1.6x | | single-row UPDATE | 100,000 | 5.5 us | 11.6 us | 2.1x | | single-row UPDATE | 1,000,000 | 5.3 us | 10.5 us | 2.0x | | single-row DELETE | 100,000 | 4.8 us | 8.3 us | 1.7x | | single-row DELETE | 1,000,000 | 4.3 us | 7.9 us | 1.8x | | point SELECT by key | 100,000 | 4.6 us | 3.8 us | tie (0.8x, within noise) | | point SELECT by key | 1,000,000 | 4.0 us | 4.0 us | tie (1.0x) | Transactions (EXP-PB4, 1,000,000 rows; the 100,000-row figures follow the same pattern; this experiment ran before the compilation setting of EXP-PB5 was added, so these engine times are an upper bound and were not re-measured): | Operation | SQLite | HoloDb engine | |---|---|---| | BEGIN | 3.2 us | 0.8 us | | 1,000 single-row UPDATEs inside BEGIN, then COMMIT | 6.44 ms | 28.18 ms | | the same, then ROLLBACK | 6.54 ms | 33.35 ms | `BEGIN` costs the same at any table size because rows are journaled as they change instead of the table being copied; `ROLLBACK` replays the journal. Atomicity and crash recovery are covered by `acidstmt` (48 checks: a failing log append is undone in full, a reopen from the log reproduces the committed state) and `txnundo` (58 checks plus about 600 randomized comparisons against SQLite; three deliberate mutations each turned it red). ### Queries without the plane, and the plane, at 1,000,000 rows (EXP-PB2 re-run, EXP-PB3, EXP-PB5) Seventeen query classes on a 1,000,000-row table. This is the re-run of the pre-registered benchmark after the engine's scan, group-by, join and transaction work; its control query (a query the plane declines, so both sides run the same engine path) read 0.81 against a registered band of 0.8 to 1.25, so the measurement is unbiased, narrowly. An earlier pass of the same size read 0.73 and is not reported. | Query class | SQLite | HoloDb engine | HoloDb plane | Plane vs engine | |---|---|---|---|---| | COUNT(*) whole table | 417.4 us | 1.6 us | 3.3 us | slower (0.48x) | | SUM(qty) whole table | 40.25 ms | 1.8 us | 3.8 us | slower (0.47x) | | GROUP BY 1 column | 288.46 ms | 4.4 us | 10.2 us | slower (0.43x) | | GROUP BY 2 columns | 484.34 ms | 2.88 ms | 2.40 ms | tie (1.20x) | | WHERE = on 1 column | 48.11 ms | 1.28 ms | 3.8 us | 336x faster | | WHERE BETWEEN | 52.23 ms | 620.0 us | 9.2 us | not interpreted (noise) | | WHERE on 3 columns (AND/IN) | 65.19 ms | 1.63 ms | 144.2 us | 11x faster | | WHERE LIKE ... OR | 61.37 ms | 1.24 ms | 37.2 us | 33x faster | | GROUP BY with WHERE | 126.79 ms | 3.10 ms | 2.32 ms | 1.34x faster | | COUNT DISTINCT whole table | 81.41 ms | 2.1 us | 1.7 us | tie (1.24x) | | COUNT DISTINCT with WHERE | 71.71 ms | 1.91 ms | 630.7 us | 3.0x faster | | MIN/MAX of an INT column | 51.34 ms | 1.8 us | 3.4 us | slower (0.53x) | | Range count | 44.39 ms | 343.4 us | 2.7 us | 127x faster | | Join COUNT | 69.68 ms | 3.75 ms | 15.9 us | not interpreted (noise) | | Join SUM (both sides) | 108.23 ms | 4.92 ms | 85.5 us | 58x faster | | Join on a TEXT key | 327.89 ms | 37.36 ms | 8.0 us | 4,670x faster | | Query outside the plane (control) | 48.55 ms | 938.1 us | 1.16 ms (declined, engine path) | tie (0.81x) | **The join rows use a very small dimension table.** The benchmark joins the 1,000,000-row table to a 40-row table: the two INT-key joins have 40 distinct join keys, and the TEXT-key join has 4 distinct keys (4 labels, each on 10 of the 40 rows). Those key counts are far below the roughly 2,000 product keys of workload C above and the 200,000 join keys of the billing workload, so these join figures say little about joins over many keys. How to read it. **The engine alone is faster than SQLite on every class, from 9x (the TEXT join) to more than 250x on COUNT(*) and more than 20,000x on SUM, single-column GROUP BY, MIN/MAX and COUNT DISTINCT over the whole table.** The plane is faster than SQLite on every class it serves, and against the engine it now wins where there is a real scan or join to avoid: the filters, the joins, COUNT DISTINCT with a WHERE. It does not win the whole-table and single-column classes, where the engine reads a maintained total in nanoseconds (the default routing, `PleromaMode.Auto`, sends those to the engine), and it only ties the two-column GROUP BY at this size. Outcome counts for the plane against the engine: 7 classes at least 2x faster, 3 ties, 1 between 1.25x and 2x, 4 slower, 2 not interpreted. **Other sizes of the same re-run** (the control read 0.99 at 100,000 rows and 1.11 at 300,000, both inside the band). At 100,000 rows the engine is faster than the plane on seven of the 17 classes: the whole-table classes, the single-column GROUP BY and MIN/MAX (0.33x to 0.51x), the two-column GROUP BY (0.26x), GROUP BY with a WHERE (0.41x) and COUNT DISTINCT with a WHERE (0.58x); the plane is faster on the three-column WHERE (5.2x), LIKE ... OR (15x), BETWEEN (29x), the range count (62x), the equality filter (95x), the join SUM (41x) and the TEXT join (2,700x). At 300,000 rows the plane is faster on every filter and join (24x to 1,887x) and on the two-column GROUP BY (1.77x), and the engine is faster on GROUP BY with a WHERE (0.73x). Default routing sends GROUP BY with a WHERE to the engine below 140,000 rows. **Costs of the plane when it is attached** (same re-run, plane against the engine alone): - Single-row INSERT: 15.4, 9.3 and 16.1 us against 8.3, 6.5 and 9.6 us (100,000, 300,000 and 1,000,000 rows), so the plane adds 1.4x to 1.9x. UPDATE: 24.2, 13.3 and 27.4 us against 13.6, 8.3 and 15.8 us (1.6x to 1.8x). These cells are microseconds and move with the order the two arms run in (the INSERT ratio at 100,000 rows read 1.9x or 2.3x depending on which arm ran first). - Batch load of the whole table: 1.93 s with the plane against 1.80 s without at 1,000,000 rows (1.07x); SQLite loaded the same rows in 1.80 s. Rebuilding the plane from the columns takes 131 ms at that size. - One INSERT followed by a two-column GROUP BY, repeated: engine 1.35 ms, 4.25 ms and 8.16 ms per pair against the plane's 3.24 ms, 2.89 ms and 3.84 ms (100,000, 300,000 and 1,000,000 rows), so the plane pays a roughly 3 ms floor that the engine is faster than on small tables and slower than on large ones. - Memory: the plane's cells are 0.92 B per row at 1,000,000 rows (a flat 0.92 MB joint slice whatever the row count); the database's heap is 139.7 B per row with the plane against 135.2 B without, a difference of about 4.5 MB (1.9 MB in the earlier 1,000,000-row runs, 1.9 MB at 300,000 rows and 4.6 MB at 100,000 rows). - After all the writes the plane and the engine agreed on all 17 queries and the plane equalled a rebuild from the columns. Single-row DELETE inside this benchmark is not reported: its loop draws ids with replacement and mixes in transaction overhead, so it does not measure the statement. The single-row DELETE figure is the autocommit one in the table above. The TEXT-key join is faster than SQLite in the engine alone (EXP-PB3: 39.98 ms against 322.17 ms at 1,000,000 rows, rows identical). It requires both join columns to be TEXT; a join between an INT column and a TEXT column takes the general path and is much slower. **Limits that are still open.** One run per size on one machine; one synthetic table (9 columns, four small-domain dimensions, a 14-bit joint). The plane serves only the columns you attach, lives in RAM and is not persisted. In the engine alone: GROUP BY with a WHERE is 3 ms at 1,000,000 rows because the filter and the grouping are separate passes; the dense-code GROUP BY covers INT and TEXT columns whose combined distinct count is at most 65,536, and anything else (REAL group keys, higher cardinality) uses a slower string-key path; REAL aggregates over a filter use the older scan; a 1,000-statement transaction is 4 to 5 times SQLite's cost; after a `ROLLBACK` of deleted rows the table holds the same rows but not necessarily in the same internal order. The first DDL statement inside a transaction takes a snapshot of every in-RAM table (so it costs time proportional to the data), and autocommit CREATE INDEX and ALTER clone the one table they change. The server single-row lookup includes about 0.07 ms of client, TLS and socket cost that is outside the engine; SQL Server's 0.07 ms and SQLite's 0.01 ms are both below HoloDb server's 0.18 ms, and SQLite is ahead of embedded HoloDb on the lookup (0.01 ms against 0.02 ms). Still behind DuckDB on the billing workload: the signup-cohort join (1.25x, a parallel scan of the 10 million invoices at about 80 ns per row per core); tied with it on the big-ticket count and the enterprise-revenue join. The Pleroma plane is not part of the main comparison and does not help the billing joins (200,000 join keys against the limit of 4,095) or the top-customers query (see the plane section above); a plane join over fewer keys is served, as in workload C above. A GROUP BY with more than 64 distinct values is not served from the live snapshot and can wait behind a continuous writer (see the dashboard-read measurement above). Page-store throughput is not reported here: earlier figures came from other conditions, were not published, and are not comparable with a current run. The aggregate plane is separate from the 5.0.0 page-store additions (check prime, parity, striped reads): none of them is on the plane's path, and the benchmarks above do not exercise them. ## Getting it / minimal example ``` dotnet add package EvaluatedApplications.HoloDb ``` ```csharp using HoloDb; var db = new HoloDbService(new HoloDbOptions { WalPath = "app.wal" }); db.Execute("CREATE TABLE users (id INT PRIMARY KEY, age INT, name TEXT)"); db.Execute("INSERT INTO users VALUES (1, 30, 'Ada')"); var result = await db.ExecuteAsync("SELECT name FROM users WHERE age >= 18"); foreach (var row in result.Rows) Console.WriteLine(row["name"]); ``` Register it with dependency injection via `services.AddHoloDb()`, or attach it to an EvalApp pipeline with `builder.WithHoloDb(service)` and query it from any step. `Execute`/`ExecuteAsync` work the same way whether the table is an ordinary in-memory table or a paged, durable, larger-than-memory one. ## License Proprietary: this package ships the compiled library only; see `LICENSE` for the full terms. Installing and using unmodified copies for internal evaluation and non-commercial development or testing is licensed; commercial, production, or revenue-generating use requires a separate commercial licence from the owner. No feature on this page is gated behind a tier or a licence key: every capability described works identically with or without one. Copyright (c) 2026 Dongyang Stephen Chen, trading as Evaluated Applications. All rights reserved. ## Anything else worth knowing - No `UPSERT`: inserting an existing primary key always throws; callers that want upsert semantics do `DELETE` then `INSERT`, or check existence first. - One `PRIMARY KEY` per table; no outer joins yet. `ALTER TABLE` supports `ADD COLUMN ... DEFAULT ` only, no `DROP`, rename, or type-change. - `NEAREST ... WHERE` filters first and then ranks the survivors; `NEAREST` does not combine with `GROUP BY`. - The Pleroma plane is in-RAM tables only. Built from SQL (`CREATE INDEX name ON t (dims) INCLUDE (measures) USING SUMMARY`, removed with `DROP INDEX name`, listed by `SHOW INDEXES`) it is rebuilt after a restart and a checkpoint; built by `EnablePleroma` it is not persisted (call it again after `Open`). A paged table refuses it. The sparse page store has no parity groups, restore points or event journal yet; the dense store has all three. - Ships as a compiled library only (no XML doc/IntelliSense from the package itself); source is proprietary and not distributed. - HoloDb is plain managed .NET with no native dependencies, so the exact same package also runs unmodified inside a Blazor WebAssembly app in a visitor's browser tab, nothing HoloDb-specific was built to make that work, it falls out of being ordinary .NET. This isn't a HoloDb feature so much as a fact about a CONSUMER: this site's own Showroom tools app (a separate NuGet-only Blazor WASM project, not part of HoloDb) proves it with an in-browser diagnostic page that fetches a HoloDb database file, writes it into the WASM virtual filesystem, and opens/queries it with the ordinary `Database.Open`/`Execute` API, entirely client-side. That page is a spike proving the mechanism works, not a shipped content pipeline, nothing on the live site's real content runs through it today, and only HoloDb's legacy in-memory + WAL mode has been proven this way (the paged `Store/` engine hasn't been tried in a browser). ================================================================================ # HoloDb.Client — EvaluatedApplications.HoloDb.Client Page: https://evaluatedapplications.github.io/holodb-client.html Install: dotnet add package EvaluatedApplications.HoloDb.Client ================================================================================ A .NET client library for remote HoloDb database servers over TLS. What it does: HoloDb.Client connects your .NET app to a HoloDb server over TCP with mandatory TLS encryption and token authentication. Run SQL queries and bulk-load data using the same API as the embedded in-process HoloDbService, so you can swap from embedded to networked by changing only how you create the handle. Columnar results stay columnar on the wire — no row buffering or JSON serialization overhead. The problem: building analytics or database-driven apps means choosing between speed (embed the database in-process) and scalability (run it on its own server). This library lets you have both. Why HoloDb.Client: same API embedded or networked (Execute, ExecuteAsync, BulkLoadAsync, GetStatsAsync, PingAsync); columnar over the wire (typed column arrays, matching the in-process engine's QueryResult shape); secure by default (TLS on, trust a self-signed server via a pinned thumbprint or skip it in dev only); built-in resilience (v1.4.0 — optional exponential backoff with full jitter, a circuit breaker, and a per-operation deadline budget); designed for concurrency (one client per worker, or pool clients with HoloDbClientPool). Version history: v1.4.0 added operation deadline budgets across retries and circuit-breaker state; v1.3.0 added a circuit breaker; v1.2.0 switched to exponential backoff. Minimal example: ```csharp using HoloDb.Client; var client = await HoloDbClient.ConnectAsync("db.example.com", 5433); try { var result = await client.ExecuteAsync("SELECT id, value FROM data LIMIT 10"); foreach (var row in result.Rows) { Console.WriteLine($"id={row[0]}, value={row[1]}"); } } finally { await client.DisposeAsync(); } ``` Requirements: .NET 8.0 or .NET 10.0; a HoloDb server v1.4.0+ (wire-protocol compatible); network connectivity to the server with TLS support. One client = one session (requests serialize through an internal queue). License: proprietary, part of Evaluated Applications — evaluation and non-commercial use are permitted; commercial use requires a commercial licence. ================================================================================ # HoloDb.Protocol — EvaluatedApplications.HoloDb.Protocol Page: https://evaluatedapplications.github.io/holodb-protocol.html Install: dotnet add package EvaluatedApplications.HoloDb.Protocol ================================================================================ A columnar wire protocol: the contract between HoloDb server and client, keeping column-oriented performance alive on the wire. What it does: HoloDb.Protocol defines how the HoloDb server and client communicate. Instead of sending results as JSON or row-by-row data structures, it preserves the columnar shape: a long[], double[], or string[] travels as a typed array over the wire. Handles length-prefixed TCP framing, a binary columnar codec, request/response dispatch (Hello/Exec/BulkLoad/Stats/Ping), version negotiation, and error semantics that distinguish protocol errors from query errors. Why it matters: most database protocols trade columnar performance for JSON or ORM convenience; this protocol keeps the columnar win alive all the way to the client, and encodes the wire format explicitly (predictable, versionable, testable). .NET 8.0 / 10.0, nullable-enabled. Check the live NuGet listing (EvaluatedApplications.HoloDb.Protocol) for the exact current version. How to get it: normally pulled in transitively via EvaluatedApplications.HoloDb.Client. If you are implementing a server (or working on HoloDb's server code), depend on this package directly. Minimal example (server-side, using this package to build a server): ```csharp var payload = await Wire.ReadFrameAsync(networkStream); var request = HoloProtocol.DecodeRequest(payload); if (request.Op == WireOp.Exec) { var result = await engine.ExecuteAsync(request.Sql); var response = HoloProtocol.Result(result); await Wire.WriteFrameAsync(networkStream, response); } ``` Client-side, use HoloDb.Client instead, which wraps this protocol. Compatibility & wire stability: the wire format is frozen — opcode byte values never change, message field order and types are stable. Most consumers should depend on HoloDb.Client instead; depend on this package directly only if implementing a server. ================================================================================ # HoloVoxel — EvaluatedApplications.HoloVoxel Page: https://evaluatedapplications.github.io/holovoxel.html Install: dotnet add package EvaluatedApplications.HoloVoxel ================================================================================ A holographic voxel engine for .NET where level-of-detail isn't a mesh trick, it's how reading the world works. What it does: most voxel engines store a world as arrays of blocks and fake distant detail with mesh simplification, mipmaps, or LOD popping. HoloVoxel stores a chunk of the world as one holographic superposition instead: every voxel is bound (position ⊗ content) and summed into a single vector, using the Phasor VSA codec. Reading a voxel back is a correlation against that vector, and correlating with fewer components gives a cheaper, fuzzier answer — near stays crisp, far goes soft, with no discrete LOD tiers and no popping between them. The engine also exposes a decoded-confidence signal a renderer can map to visual solidity. Why it's different: LOD is free (no separate simplified mesh to generate, store, or stitch); memory scales with perceived detail, not world size (a chunk only stores as many components as its LOD will ever need, losslessly up to that budget); the blur is honest, not aesthetic (distant terrain looks soft because the engine genuinely has less information at that budget); engine only, plug into anything (no rendering or graphics dependency, verified headless). Check the live NuGet listing (EvaluatedApplications.HoloVoxel) for the exact current version. Key features: holographic chunk storage (HoloWorld, Chunk) decodable at any component budget as a colour field or a triangulated surface mesh with analytic per-vertex normals; continuous, meshless LOD; field confidence for adaptive detail; spatial coarsening at distance; truncated holograms (storage cost tracks the LOD budget you plan to read at); fused SIMD bind/correlate; entities too (HoloModel stores a creature or prop the same holographic way); a built-in procedural world generator, or supply your own world source; a ringworld warp on top of the same flat chunk storage. Good to know: this is the engine, not the renderer — HoloVoxel has no graphics dependency and is verified headless, handing you decoded colour fields, meshes, and confidence values; drawing them is up to the consuming front end. Built on Phasor. DLL-only distribution, proprietary license — evaluation and non-commercial use are permitted; commercial use requires a commercial licence; no feature is gated behind a tier or a license key. NOTE: this package's owner-authored site.md does not include a minimal code sample; none is invented here. See the API description above and the package's own CLAUDE.md for exact call shapes, or ask the package owner for one. ================================================================================ # Prose — EvaluatedApplications.Prose Page: https://evaluatedapplications.github.io/prose.html Install: dotnet add package EvaluatedApplications.Prose ================================================================================ A grammar-driven synthetic corpus generator for .NET. What it is: Prose reads plain text through the rules of grammar, keeps what it learns in a HoloDb database, and recombines that knowledge into new sentences that are grammatical, use words suited to their slots, and read plausibly. It exists to grow a training corpus: mine the grammatical knowledge already in your text (which nouns, verbs and adjectives go together, and how), then generate more of it, along with question/answer pairs for reading-comprehension training data. The problem it solves: language models need volume and variety of grammatically correct text. Hand-writing or scraping more data doesn't scale, and most "data augmentation" either pastes fragments together ungrammatically or needs its own large model to run. Prose parses real text into its grammatical structure with deterministic rules, stores what nouns/verbs/adjectives actually co-occur with what, and recombines those attested pieces into fresh sentences guaranteed to parse correctly before they're ever written out. Why it's different: rules-first, not model-first (a small optional language model can rank candidates by plausibility, but Prose degrades gracefully to pure rules with no model at all); no word is locked to one role (the same surface form resolves to noun or verb by context, e.g. "the panda eats shoots and leaves" vs "the panda eats, shoots, and leaves" — punctuation and structure alone flip the reading, and Prose gets both right); nothing imaginary (every open-class word Prose emits is a form it actually observed in the source text); handles real grammatical structure (indirect objects, relative clauses, multi-sentence passages with coreference), not just word salad. Check the live NuGet listing (EvaluatedApplications.Prose) for the exact current version. Key features: parse (sentence splitting, POS tagging, phrase chunking, role assignment, zero training, no external model); mine (builds a lexicon plus selectional tables in a HoloDb database); generate (samples a sentence shape, fills each slot with an attested agreement-correct word, keeps only sentences that re-parse validly); optional plausibility scoring; Q&A generation (single- sentence, multi-sentence passages with coreference, self-referential two-turn dialogues); corpus and TSV export. Minimal example: ```csharp var prose = new ProseEngine(); prose.Mine(@"C:\corpus\text"); // parse every *.txt and mine it prose.Save(@"prose.wal"); // persist the mined tables (optional) foreach (var sentence in prose.Generate(1000)) // new, grammatical, plausible sentences Console.WriteLine(sentence); prose.WriteCorpus(@"C:\corpus\synthetic", 100_000); // write sentences out as .txt for an LM prose.WriteQaPairs(@"C:\corpus\qa", 50_000); // context+question -> answer TSV ``` Parse a single sentence directly, no mining or database required: ```csharp var p = ProseEngine.ParseSentence("The panda eats, shoots, and leaves."); Console.WriteLine(ProseEngine.Explain(p)); // subject, verbs, objects, template ``` Good to know: depends on two other Evaluated Applications packages, HoloDb (storage engine) and AlgFormer (optional plausibility-scoring model) — installing this package pulls both in automatically. Ships as a compiled library under a proprietary licence — evaluation and non-commercial use are permitted; commercial use requires a commercial licence; no feature is gated in code. ================================================================================ # Tracer — EvaluatedApplications.Tracer Page: https://evaluatedapplications.github.io/tracer.html Install: dotnet add package EvaluatedApplications.Tracer ================================================================================ Navmesh pathfinding and game AI for .NET: multi-agent path queries, dynamic obstacles, line-of-sight, and combat, all self-tuning to your frame budget. Tracer is a pathfinding and game-AI SDK for real-time simulations with many moving agents: crowds, RTS-style unit groups, tactical squads. It bakes triangle-based navmeshes, routes single agents and whole swarms across them, reacts to obstacles that appear or vanish mid-game, and layers the surrounding game-AI toolkit (line-of-sight, fog-of-war, influence maps, combat engagement) on top. The problem it solves: most pathfinding libraries stop at "find me a path." Real games need a lot more: hundreds of agents converging on the same goal without re-solving the same route hundreds of times; obstacles that block and unblock at runtime without a full re-bake; visibility and cover queries for AI perception; a frame-time budget the pathfinder has to live inside of. Tracer builds all of that in as one coherent SDK, running on a data-parallel pipeline (EvalApp) that tunes its own concurrency to the workload. What it does: navmesh baking (with obstacle-polygon exclusion, optional hierarchical bake); single- and multi-agent pathfinding (goal-sharing so agents converging on one point reuse the same solve); dynamic obstacles (block/unblock at runtime without a full re-bake); line-of-sight, fog-of-war, influence maps; combat engagement (spatial-hashed, pluggable damage/dodge/block formulas); steering behaviors (Seek, Wander, Patrol, Flee, Queue, FlowLane); grid tactics (a separate, bake-free lane for tile/square-grid tactics games); adaptive path budgeting under a tight frame budget. Check the live NuGet listing (EvaluatedApplications.Tracer) for the exact current version. Minimal example: ```csharp using Tracer; var world = new PathfindingWorld(); var baker = world.CreateNavMeshBakerService(); var mesh = await baker.BakeAsync(vertices, triangleIndices); var single = world.CreateSingleAgentService(); var waypoints = await single.QueryPathAsync(mesh, start, goal); var multi = world.CreateMultiAgentService(); var result = await multi.TickAsync(agents, mesh, tickNumber: 0); ``` What you need to know: depends on EvalApp (self-tuning concurrency for every heavy tick) and Microsoft.Extensions.DependencyInjection.Abstractions. Target .NET 8.0 and .NET 10.0. License: proprietary — evaluation and non-commercial use are permitted; commercial use requires a commercial licence; no feature is gated behind a tier or a license key. Proven in use building the Eden game project (navmesh movement, perception/fog, combat resolution, tactical squad control). ================================================================================ END OF FILE — https://evaluatedapplications.github.io/llms.txt has the short version, the tool list, and our partnership offer.