TL;DR: Many AI code tools claim "graph-based context reduction" using PageRank. I tested this on a real project and found that Top 20% of files by PageRank give only -2% savings (worse than reading everything). Here's why the math breaks down for codebases.
The Promise
You've seen the marketing:
"We build a call graph of your codebase, run PageRank, and only send the most important files to the LLM. 60% token savings!"
Sounds great. But does it actually work?
I decided to measure it on a real project.
The Setup
Project: MSCodeBase Intelligence (50K LOC Python)
Method:
- Build call graph from PropertyGraph (nodes = files, edges = imports/calls)
- Run PageRank to rank files by importance
- Measure token count for Top 10%, 20%, 50% of files
- Compare with full context baseline
Tools:
- PropertyGraph with 4,473 nodes and 5,733 edges
- PageRank implementation with damping factor 0.85
- Token counting via tiktoken (cl100k_base)
The Results
| Selection | Files | Tokens | Savings vs Full | Accuracy (10 queries) |
|---|---|---|---|---|
| Full context | 100% (127) | 137,290 | baseline | 63.3% |
| Top 10% PageRank | 10% (12) | 10,598 | +92.3% | 23.3% |
| Top 20% PageRank | 20% (25) | 26,450 | +80.7% | 23.3% |
| Top 50% PageRank | 50% (63) | 68,493 | +50.1% | 30.0% |
The Trade-off
Top 10% saves 92% of tokens but accuracy drops from 63% to 23%. That's a 40 percentage point accuracy loss for token savings. The question is: is that worth it?
Why PageRank Doesn't Reduce Context (Naïve File-Level)
Problem 1: Power Law Distribution of File Sizes
File sizes in codebases follow a power law. A few hub files (runtime_coordinator.py, indexer.py, searcher.py) contain most of the semantic volume, while 80% of the "tail" is small utilities under 50 lines each.
This isn't a coincidence — centrality metrics (PageRank, in-degree) correlate with LOC because large files both import more and are referenced more often. Top-20% by PageRank ≈ top-20% by LOC ≈ 98% of tokens.
Problem 2: Centrality ≠ Relevance
PageRank measures structural importance, not query relevance. A utility file with 50 imports might rank high (centrality) but be irrelevant to most queries. This is why tools like Aider and CodeGraph moved to on-demand retrieval — they query the graph at runtime under a specific query, not pre-select files.
Problem 3: The Long Tail is Cheap
The remaining 80% of files (212 files) only contain 2,536 tokens total. That's 2% of the context. You're saving almost nothing by excluding them.
What Actually Works
Based on my experiments, here's what reduces context effectively:
1. Smart Summary (98.4% savings, 90% accuracy)
Instead of sending full files, build a 2K token summary:
- File names + key symbols
- Import graph
- PageRank scores (for prioritization, not reduction)
This gives 90% accuracy with 98.4% fewer tokens.
2. Query-Based Retrieval (variable savings)
Instead of pre-selecting files, retrieve relevant chunks on-demand:
- BM25 for keyword matching
- Vector search for semantic similarity
- Reranker for precision
This is what tools like Cursor and GitHub Copilot actually do.
3. Layer Filtering (30-50% savings)
Filter by architecture layer (core/mcp/utils/tests) based on query intent:
- "How does search work?" → core/search only
- "Where is the bug?" → recent changes + hotspots
- "Add a feature" → interface + provider layers
The Math Behind It
The power law distribution means a few files contain most tokens:
Total: 127 files, 137,290 tokens
Top 10%: 12 files, 10,598 tokens (92.3% savings)
Top 20%: 25 files, 26,450 tokens (80.7% savings)
Top 50%: 63 files, 68,493 tokens (50.1% savings)
But accuracy tells the real story:
Top 10%: 23.3% accuracy (10/127 files = massive loss)
Top 20%: 23.3% accuracy (still terrible)
Top 50%: 30.0% accuracy (barely better)
Top 100%: 63.3% accuracy (baseline)
The problem: centrality ≠ relevance. The most "important" files by PageRank are the biggest ones (hub files), not the ones relevant to a specific query.
What This Means
For AI code tools:
- PageRank is good for ranking, not reduction
- Use it to prioritize which chunks to retrieve, not which files to exclude
- Combine with query-based retrieval for best results
For developers:
- Don't trust "X% token savings" claims without seeing the accuracy metric
- A tool that saves 60% tokens but misses 30% of relevant code is worse than full context
- The best context is the right context, not less context
Caveat: This is one project (50K LOC Python) on one language. Numbers will differ on other codebases, but the power law distribution of file sizes is universal — so the trend holds.
The Experiment Code
import networkx as nx
import tiktoken
# Build graph from PropertyGraph
G = nx.DiGraph()
for node in graph.get_nodes():
G.add_node(node.id, label=node.label)
for edge in graph.get_edges():
G.add_edge(edge.source, edge.target, type=edge.type)
# Run PageRank (directed graph — CALLS/IMPORTS edges are directional)
pr = nx.pagerank(G, alpha=0.85)
# Sort by importance
sorted_files = sorted(pr.items(), key=lambda x: x[1], reverse=True)
# Measure tokens
enc = tiktoken.get_encoding("cl100k_base")
full_tokens = sum(len(enc.encode(f.read_text())) for f in all_files)
for top_n in [10, 20, 50]:
top_files = [f for f, _ in sorted_files[:int(len(sorted_files) * top_n / 100)]]
top_tokens = sum(len(enc.encode(f.read_text())) for f in top_files)
savings = (full_tokens - top_tokens) / full_tokens * 100
print(f"Top {top_n}%: {savings:.1f}% savings")
Related Work
-
Aider uses symbol-level elision (not file-level) — it extracts "the most important identifiers" via RepoMapper and fits them into a token budget (
--map-tokens). This is smarter than file-level, but still suffers from the same power law issue: the most important symbols live in the biggest files. - CodeGraph (61k stars) does on-demand graph traversal at query time, not pre-selection. This is the right approach.
- Codebase-Memory (DeusData, arXiv) publishes honest metrics: 83% quality vs 92% for file-exploration, with 10x fewer tokens.
My measurement here is for the naïve file-level baseline — what happens when you take centrality literally and send files whole. The industry has already moved beyond this, but I haven't seen anyone publish the numbers.
Discussion
Has anyone else measured PageRank effectiveness on their codebase? I'd love to see results from larger projects (100K+ LOC).
What context reduction strategies actually work in your experience?
Reproduce this yourself: the script is in experiments/run_experiment_pagerank.py. Run it on your project and share results.
Part of my research on MSCodeBase Intelligence — an MCP server for codebase intelligence.
Top comments (0)