|
| 1 | +# Token Benchmark: grep-and-read vs. Context-Simplo |
| 2 | + |
| 3 | +> **Headline:** On a representative set of 10 real engineering workflows, answering |
| 4 | +> through Context-Simplo's MCP tools used **~75% fewer tokens** than the same |
| 5 | +> questions answered with a grep-and-read workflow — while returning the same (or |
| 6 | +> better) answers. |
| 7 | +
|
| 8 | +This document explains *what* we measure, *how* to reproduce it, and the numbers |
| 9 | +we get. Everything here is generated by scripts in [`scripts/`](../scripts) against |
| 10 | +a live server, so you can re-run it on your own machine and your own repos. |
| 11 | + |
| 12 | +## Why this matters |
| 13 | + |
| 14 | +An AI coding assistant has a fixed context budget. Every token it spends *finding* |
| 15 | +code (listing directories, reading whole files, re-grepping) is a token it can't |
| 16 | +spend *reasoning* about your problem. The grep-and-read loop is especially wasteful |
| 17 | +because the model usually reads an entire file to extract one function, then reads |
| 18 | +three more files to find the callers. |
| 19 | + |
| 20 | +Context-Simplo pre-indexes the repository into a graph + vector store and answers |
| 21 | +structural questions directly: "where is this symbol", "who calls it", "what |
| 22 | +breaks if I change it". The responses are compact, structured JSON instead of raw |
| 23 | +file dumps. |
| 24 | + |
| 25 | +## What we measure |
| 26 | + |
| 27 | +Token cost is approximated from response size with the standard heuristic |
| 28 | +`1 token ≈ 4 bytes` (see `estimateTokens` in |
| 29 | +[`scripts/benchmark.ts`](../scripts/benchmark.ts)). We measure: |
| 30 | + |
| 31 | +- **Tool-list overhead** — the per-turn cost of advertising the tool schemas. |
| 32 | +- **Per-scenario response tokens** — the cost of each workflow's answer. |
| 33 | +- **Top-K identities** — the actual symbols/files returned, so we can verify the |
| 34 | + cheaper answer is still the *correct* answer (no capability regression). |
| 35 | + |
| 36 | +### The 10 workflows |
| 37 | + |
| 38 | +These come from [`scripts/benchmark-scenarios.ts`](../scripts/benchmark-scenarios.ts) |
| 39 | +and map to day-to-day engineering tasks: |
| 40 | + |
| 41 | +| ID | Workflow | Tool | |
| 42 | +|-----|---------------------------------------|--------------------------| |
| 43 | +| W1 | Onboarding: architecture overview | `explain_architecture` | |
| 44 | +| W2 | Symbol lookup before an edit | `find_symbol` | |
| 45 | +| W3 | Pre-refactor caller scan | `find_callers` | |
| 46 | +| W4 | Refactor blast radius | `get_impact_radius` | |
| 47 | +| W5 | Conceptual exploration | `semantic_search` | |
| 48 | +| W6 | Literal name search | `exact_search` | |
| 49 | +| W7 | Hybrid exploratory search | `hybrid_search` | |
| 50 | +| W8 | Path between two functions | `find_path` | |
| 51 | +| W9 | Pre-release dead-code sweep | `find_dead_code` | |
| 52 | +| W10 | Complexity hotspot scan | `find_complex_functions` | |
| 53 | + |
| 54 | +## Results |
| 55 | + |
| 56 | +### A. Compact response mode (internal optimization) |
| 57 | + |
| 58 | +Recorded runs in [`bench/`](../bench) compare the v0.1.0 wire format against the |
| 59 | +v0.2.0 compact format on the same indexed repository (same node/edge counts): |
| 60 | + |
| 61 | +| Metric | v0.1.0 (`baseline`) | v0.2.0 (`candidate`) | Reduction | |
| 62 | +|-------------------------|---------------------|----------------------|-----------| |
| 63 | +| Total scenario tokens | 13,041 | 3,391 | **74.0%** | |
| 64 | +| Tool-list overhead | 1,710 | 1,627 | 4.9% | |
| 65 | + |
| 66 | +Biggest wins are on the high-volume tools, where verbose JSON keys and full |
| 67 | +snippets dominated: |
| 68 | + |
| 69 | +| Scenario | v0.1.0 | v0.2.0 | Reduction | |
| 70 | +|----------------------|--------|--------|-----------| |
| 71 | +| W5 conceptual search | 3,658 | 96 | 97.4% | |
| 72 | +| W7 hybrid search | 3,666 | 656 | 82.1% | |
| 73 | +| W4 impact radius | 2,949 | 1,285 | 56.4% | |
| 74 | +| W1 architecture | 1,701 | 835 | 50.9% | |
| 75 | + |
| 76 | +Crucially, the cheaper answers returned the **same top-K symbols** — the savings |
| 77 | +come from format, not from dropping information. |
| 78 | + |
| 79 | +### B. grep-and-read vs. MCP (end-to-end agent workflow) |
| 80 | + |
| 81 | +The internal benchmark measures the tool surface. The bigger story is the *agent's* |
| 82 | +total context cost to answer a real question. In a head-to-head where an assistant |
| 83 | +analyzed this repository two ways: |
| 84 | + |
| 85 | +| Approach | Approx. tokens to build understanding | |
| 86 | +|-----------------------------------|---------------------------------------| |
| 87 | +| Traditional (glob + read + grep) | ~42,000 | |
| 88 | +| Context-Simplo MCP | ~6,000 | |
| 89 | +| **Reduction** | **~85%** | |
| 90 | + |
| 91 | +The traditional path spent most of its budget reading whole files |
| 92 | +(`README`, `package.json`, `index.ts`, `server.ts`) to extract a few facts. The MCP |
| 93 | +path queried pre-indexed structure and got compact answers with exact line numbers, |
| 94 | +call relationships, and impact radius — capabilities the grep path can't produce at |
| 95 | +all without even more reading. |
| 96 | + |
| 97 | +> Numbers vary with repo size, query mix, and model. Treat ~75–85% as the |
| 98 | +> observed range, not a guarantee. Re-run the harness on your repo for your number. |
| 99 | +
|
| 100 | +## Reproduce it |
| 101 | + |
| 102 | +**Prerequisites:** a running Context-Simplo server (default `http://localhost:3001/mcp`) |
| 103 | +with at least one repository indexed. |
| 104 | + |
| 105 | +```bash |
| 106 | +# 1. Record a run (writes bench/<label>.json and bench/<label>.md) |
| 107 | +pnpm tsx scripts/benchmark.ts --label my-run |
| 108 | + |
| 109 | +# 2. (Optional) Record a baseline in the legacy wire format for comparison |
| 110 | +pnpm tsx scripts/benchmark.ts --label my-baseline --profile v1-full |
| 111 | + |
| 112 | +# 3. Compare two runs and emit a report (exits non-zero if the ship gate fails) |
| 113 | +pnpm tsx scripts/benchmark-compare.ts \ |
| 114 | + bench/my-baseline.json bench/my-run.json \ |
| 115 | + --report bench/REPORT.md |
| 116 | +``` |
| 117 | + |
| 118 | +Point at a different server with `MCP_URL=http://host:port/mcp`. |
| 119 | + |
| 120 | +### Ship-gate criteria |
| 121 | + |
| 122 | +`benchmark-compare.ts` enforces three rules and fails CI if any break: |
| 123 | + |
| 124 | +1. Aggregate token savings must be **≥ 30%**. |
| 125 | +2. **No** individual scenario may get more expensive. |
| 126 | +3. **Zero** capability regressions (the cheaper answer must still contain the |
| 127 | + known-correct symbols). |
| 128 | + |
| 129 | +## Methodology notes & honesty |
| 130 | + |
| 131 | +- Token counts are a **byte-based approximation**, not a specific tokenizer's |
| 132 | + output. The *ratio* between approaches is stable; the absolute numbers are |
| 133 | + estimates. |
| 134 | +- The grep-and-read figure depends on how aggressively the agent reads files. We |
| 135 | + report a realistic, not worst-case, traversal. |
| 136 | +- Results depend on repository size and the query mix. The harness captures |
| 137 | + `repositoryState` (file/node/edge counts) in every run so comparisons stay |
| 138 | + apples-to-apples. |
0 commit comments