DEV Community

Mikhail
Mikhail

Posted on

I Measured PageRank Token Savings on a Real Codebase. The Result Will Surprise You.

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:

  1. Build call graph from PropertyGraph (nodes = files, edges = imports/calls)
  2. Run PageRank to rank files by importance
  3. Measure token count for Top 10%, 20%, 50% of files
  4. 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)
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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")
Enter fullscreen mode Exit fullscreen mode

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)