Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Ranking quality

Speed is easy to measure and easy to game: an engine that returns the first fifty lines containing the query is fast and useless. This page tracks the thing that matters — does the first result answer the query? — with a suite of labelled queries that runs on every push and fails the build when it regresses.

What is measured

Each query in benches/ranking_quality.toml names the file (and, for text queries, the line) a reader would want first, with a one-line reason. The corpora are the pinned tokio 1.45.0 and Django 5.2 trees used by the latency benchmark, so both measurements describe the same index.

  • precision@1 — the share of queries whose first result is the expected one.
  • precision@5 — the share whose expected result is in the top five.

The CI gate is precision@1 ≥ 0.90 and precision@5 ≥ 0.95. The suite deliberately favours the cases a scan tool gets wrong: a definition that has many mentions in docs and tests, a bare identifier whose definition should beat its uses, a short name (Field) with several unrelated definitions where the widely imported one should win, and a reference query where the definition itself must not appear.

Current score

tokio 1.45.0 + Django 5.2: precision@1 1.00, precision@5 1.00 over 20 queries.

QueryModeExpected firstWhyRank found
struct Runtimetexttokio/src/runtime/runtime.rsthe definition, not the many mentions in docs and tests1
pub struct Mutextexttokio/src/sync/mutex.rstokio’s Mutex definition1
fn sleeptexttokio/src/time/sleep.rsthe free function, above test helpers named sleep1
fn block_ontexttokio/src/runtime/runtime.rs or tokio/src/runtime/handle.rsthe public Runtime::block_on / Handle::block_on, not the scheduler’s internal fn1
struct Notifytexttokio/src/sync/notify.rsthe definition1
struct Semaphoretexttokio/src/sync/semaphore.rsthe definition1
class HttpResponsetextdjango/http/response.pythe class itself, above HttpResponseRedirect and friends1
def get_object_or_404textdjango/shortcuts.pythe definition1
class QuerySettextdjango/db/models/query.pythe definition1
class ModelFormtextdjango/forms/models.pythe definition1
class Clienttextdjango/test/client.pythe test client definition1
HttpResponseBasetextdjango/http/response.pya bare identifier: its definition should beat its uses1
Runtimesymbolstokio/src/runtime/runtime.rsexact name match, the struct1
get_object_or_404symbolsdjango/shortcuts.pyexact name match1
JoinHandlesymbolstokio/src/runtime/task/join.rsthe struct, above the many impl blocks1
HttpResponsesymbolsdjango/http/response.pyexact name match over HttpResponseRedirect etc.1
Fieldsymbolsdjango/db/models/fields/__init__.pythe widely imported model Field, not the GDAL one1
pub fn sleep\(regextokio/src/time/sleep.rsliteral-accelerated regex1
^class Form\(regexdjango/forms/forms.pyanchored regex1
get_object_or_404referencesdjango/contrib/flatpages/views.pythe one call site in shipped (non-test) code; the definition itself must not be listed as a reference1

What it caught

The first run of the suite scored 0.30 at precision@1. Every miss was a ranking defect, not a missing feature, and each fix is in the changelog:

  • Items declared inside cfg_if! and similar macro bodies were invisible to the symbol extractor, so struct Runtime ranked a doc comment above the definition. The extractor now re-parses macro bodies.
  • Lines that matched only some of a multi-term query could outrank the line with the whole phrase. Phrase matches are now a strict tier above all-terms and single-term lines.
  • Test, example, mock and fixture paths carried the same weight as shipped code. They are now scaled by 0.6, and public definitions by 1.6.
  • Symbol search compared the query against names with visibility and attribute prefixes still attached, so pub struct Mutex lost to pub(crate) struct MutexGuard. Modifiers are stripped before scoring.
  • Symbol search over a large candidate set spent its per-file budget on the first files scanned in parallel, which made results depend on thread scheduling. Candidates are now scored from the symbol cache first and only the best files are scanned for matches.
  • Match budgets were consumed by whichever files finished first, so the same query could return different results on different runs. Files that contain the whole phrase are now scanned in a separate pass before the rest.
  • Reference hits all carried the same score, so ties were broken by file id, which follows discovery order: the suite scored 1.00 on a laptop and 0.95 on the CI runner, where a test’s call to get_object_or_404 came first. References now take the file’s score (dependency boost, test-path penalty) and all ties break on the path.

Running it

git clone --depth 1 --branch tokio-1.45.0 https://github.com/tokio-rs/tokio bench-corpus/tokio
git clone --depth 1 --branch 5.2 https://github.com/django/django bench-corpus/django
cargo run --release --example ranking_quality -- bench-corpus/tokio bench-corpus/django

Add --explain 'struct Runtime' (with --explain-mode symbols|regex|references for other modes) to print the top results with their scores, tiers and the factors that produced them. --min-p1 and --min-p5 turn the run into a gate, as CI does. Adding a query is a five-line TOML entry; the point of the suite is that every ranking change comes with the example that motivated it.