MemPalace.NET Benchmarks
April 25, 2026 · View on GitHub
Overview
The MemPalace.Benchmarks project provides a harness for evaluating MemPalace.NET's memory recall performance against standard benchmarks. It includes four benchmark suites and micro-benchmarks for performance profiling.
Quick Start: LongMemEval Parity Validation
To validate MemPalace.NET's recall performance against the standard LongMemEval benchmark:
# 1. Download the official dataset (500 queries, ~2.5MB)
mkdir -p artifacts/benchmarks
curl -L -o artifacts/benchmarks/longmemeval_s_cleaned.json \
https://huggingface.co/datasets/xiaowu0162/longmemeval-cleaned/resolve/main/longmemeval_s_cleaned.json
# 2. Run the benchmark with local ONNX embedder (baseline)
dotnet run --project src/MemPalace.Benchmarks -- run longmemeval \
--dataset artifacts/benchmarks/longmemeval_s_cleaned.json \
--palace artifacts/benchmarks/palace-local \
--embedder local
# Expected: R@5 ≥ 91% (target for v0.6.0)
# Python baseline: 96.6% R@5 (with nomic-embed-text)
Interpretation:
- R@5 (Recall at 5): Did the correct session appear in the top-5 search results?
- Target: ≥ 91% with local ONNX embedder (allows for embedder variance)
- Stretch target: ≥ 95% with nomic-embed-text via Ollama (closest to Python baseline)
See Parity Results section below for detailed validation status.
Benchmark Suites
1. LongMemEval
What it measures: Long-conversation memory recall across multi-session dialogues.
Dataset format: JSONL with conversation turns grouped by session_id. Each item has:
id: Unique identifierquestion: Query to test recallexpected_answer: The conversation turn to be stored as a memoryrelevant_memory_ids: IDs of memories that should be retrievedmetadata: Includingsession_idandturnnumber
Upstream reference: Inspired by conversational memory benchmarks in long-context AI research.
2. LoCoMo (Long-Context Memory)
What it measures: Long-context conversational Q&A over episodic memories.
Dataset format: Similar to LongMemEval but with episode metadata instead of sessions.
Upstream reference: Based on long-context understanding tasks.
3. ConvoMem
What it measures: Sequential turn-by-turn conversational memory with immediate recall.
Dataset format: JSONL with sequential turn metadata. Tests whether the system can recall information from earlier turns.
4. MemBench
What it measures: General memory recall on diverse factual statements.
Dataset format: JSONL with category metadata (e.g., physics, history, biology). Tests semantic retrieval across domains.
Obtaining Real Datasets
The synthetic datasets under datasets-synthetic/ are smoke fixtures only (5 items each) for CI and quick validation. They are not suitable for evaluation.
Real benchmark datasets should be obtained from:
- LongMemEval/LoCoMo/ConvoMem: Check the MemPalace Python repository for dataset links.
- MemBench: Community-contributed; check MemPalace discussions or academic papers.
Place real datasets in a directory (e.g., ./datasets/) with filenames matching the benchmark names (longmemeval.jsonl, locomo.jsonl, etc.).
QA status: real parity run (2026-04-25)
Tyrell extended the harness so LongMemEval can now consume the upstream JSON array format and rebuild a fresh haystack per question, matching the Python benchmark's session-level raw mode much more closely.
- Dataset:
https://huggingface.co/datasets/xiaowu0162/longmemeval-cleaned/resolve/main/longmemeval_s_cleaned.json - Synthetic control:
dotnet run --project src/MemPalace.Benchmarks -- run longmemeval --dataset src/MemPalace.Benchmarks/datasets-synthetic/longmemeval.jsonl --palace artifacts/benchmarks/palace-synth✅ - Real-data command shape:
dotnet run --project src/MemPalace.Benchmarks -- run longmemeval --dataset artifacts/benchmarks/longmemeval_s_cleaned.json --palace artifacts/benchmarks/palace-real --embedder local✅ supported
What changed:
DatasetLoadernow accepts both the original JSONL fixtures and the upstream LongMemEval JSON array.- Upstream
haystack_sessionsare normalized into per-question corpus documents using the same session-level "join user turns" rule as the Python benchmark. - LongMemEval now deletes and recreates its collection for each question so evaluation happens against a fresh haystack instead of one shared corpus.
- CLI commands can now use
--embedder deterministic|local|ollamainstead of always forcing the deterministic smoke embedder.
Remaining parity caveat:
--embedder localuses MemPalace.NET's default ONNX model (sentence-transformers/all-MiniLM-L6-v2), which is a real embedder but not the Python repo'snomicconfiguration.- For the closest apples-to-apples run, use
--embedder ollama --model nomic-embed-textwith a running Ollama server.
Running Benchmarks
List Available Benchmarks
dotnet run --project src/MemPalace.Benchmarks -- list
Run a Single Benchmark
dotnet run --project src/MemPalace.Benchmarks -- run longmemeval \
--dataset ./datasets/longmemeval.jsonl \
--palace ./_benchmark_palace \
--max 100
Options:
--dataset: Path to a benchmark dataset file (.jsonlfixtures or supported JSON array datasets such as upstream LongMemEval)--palace: Directory for palace storage (will be created if needed)--max: Optional limit on number of items to process--embedder:deterministic(default smoke mode),local(real ONNX model), orollama--model: Optional embedder model override--endpoint: Optional Ollama endpoint override (defaulthttp://localhost:11434)
Run a Real LongMemEval Session-Level Benchmark
dotnet run --project src/MemPalace.Benchmarks -- run longmemeval \
--dataset ./artifacts/benchmarks/longmemeval_s_cleaned.json \
--palace ./artifacts/benchmarks/palace-real \
--embedder local
For closer parity with the Python benchmark's nomic run:
dotnet run --project src/MemPalace.Benchmarks -- run longmemeval \
--dataset ./artifacts/benchmarks/longmemeval_s_cleaned.json \
--palace ./artifacts/benchmarks/palace-real \
--embedder ollama \
--model nomic-embed-text
Run All Benchmarks
dotnet run --project src/MemPalace.Benchmarks -- run-all \
--datasets-dir ./datasets \
--palace ./_benchmark_palace \
--out results.json
Options:
--datasets-dir: Directory containing{benchmark_name}.jsonlfiles--palace: Palace storage directory--max: Optional limit per benchmark--out: JSON file to save results (optional)--embedder,--model,--endpoint: Same asrun
Run Micro-Benchmarks
dotnet run --project src/MemPalace.Benchmarks -c Release -- micro
Note: Micro-benchmarks use BenchmarkDotNet and should be run in Release mode. They measure:
- Embedding throughput (embeds/sec)
- Vector query latency (1k/10k vectors, top-10 queries)
Micro-benchmarks use a deterministic embedder and don't require real models.
Result Schema
{
"BenchmarkName": "longmemeval",
"TotalQueries": 100,
"Correct": 97,
"Recall": 0.9700,
"Precision": 0.8500,
"F1": 0.9057,
"NdcgAt10": 0.9200,
"TotalDuration": "00:01:23.4567890",
"ExtraMetrics": {}
}
Metrics:
- Recall@10: Fraction of relevant memories retrieved in top-10 results (averaged across queries).
- Precision@10: Fraction of retrieved memories that are relevant (averaged).
- F1: Harmonic mean of precision and recall.
- NDCG@10: Normalized Discounted Cumulative Gain at k=10 (accounts for ranking quality).
- Correct: Number of queries with at least one relevant memory in top-10.
Synthetic Fixtures
The datasets-synthetic/ directory contains minimal smoke fixtures for each benchmark. These are used in CI to verify the harness works, not for performance evaluation.
Each fixture has 5 items and uses simple, hand-crafted data.
Development
Adding a New Benchmark
- Create a class in
Runners/implementingIBenchmark. - Extend
BenchmarkBaseto reuse ingestion/query logic. - Add the benchmark to
ListCommand.GetAllBenchmarks(). - Add a synthetic fixture under
datasets-synthetic/{name}.jsonl. - Write tests in
MemPalace.Tests/Benchmarks/.
Testing
Run the benchmark test suite:
dotnet test --filter "FullyQualifiedName~Benchmarks"
Tests use:
- InMemoryBackend for fast, reproducible execution
- DeterministicEmbedder (hash-based vectors, no real model)
- Synthetic datasets (no network/downloads)
CI Integration
The benchmark smoke tests run in CI to ensure the harness doesn't break. Real benchmarks are run separately by maintainers before releases.
Parity Targets
From the Python MemPalace implementation:
- LongMemEval R@5: ≥ 96.6% (raw embedding retrieval)
- LoCoMo R@10: ≥ 60.3% (session-based, no reranker)
These targets are based on the upstream Python implementation with nomic-embed-text. .NET results may vary depending on the embedder used; --embedder ollama --model nomic-embed-text is the closest current match.
Parity Results (v0.6.0)
Status: 🚧 Pending full validation run
Target baseline run: MemPalace.NET with sentence-transformers/all-MiniLM-L6-v2 (ONNX)
| Metric | Score | Target | Status |
|---|---|---|---|
| Recall@5 | Pending | ≥ 91% | 🚧 Validation in progress |
| Recall@10 | Pending | ≥ 95% | 🚧 Validation in progress |
| NDCG@10 | Pending | ≥ 0.85 | 🚧 Validation in progress |
| Duration | Pending | < 10 min | 🚧 Validation in progress |
Validation command:
# 1. Download LongMemEval dataset
curl -L -o artifacts/benchmarks/longmemeval_s_cleaned.json \
https://huggingface.co/datasets/xiaowu0162/longmemeval-cleaned/resolve/main/longmemeval_s_cleaned.json
# 2. Run baseline validation
dotnet run --project src/MemPalace.Benchmarks -- run longmemeval \
--dataset artifacts/benchmarks/longmemeval_s_cleaned.json \
--palace artifacts/benchmarks/palace-local \
--embedder local
Expected results:
- R@5: 88-94% (due to embedder difference: MiniLM 384-dim vs nomic 1536-dim)
- Python baseline: 96.6% R@5 with nomic-embed-text
- Delta: -2 to -8 percentage points (embedder variance is expected)
For closest parity with Python baseline:
# Requires Ollama with nomic-embed-text model
ollama pull nomic-embed-text
dotnet run --project src/MemPalace.Benchmarks -- run longmemeval \
--dataset artifacts/benchmarks/longmemeval_s_cleaned.json \
--palace artifacts/benchmarks/palace-nomic \
--embedder ollama \
--model nomic-embed-text
Expected with nomic embedder: 95-97% R@5 (within 1-2 percentage points of Python)