Skip to content

Cross-file LSP pass regressed 16.6x (21.5s → 358s on java) and is 78% of the 0.10.x indexing slowdown #1669

Description

@DeusData

Version

0.10.5 (regression against 0.9.0)

Platform

macOS arm64 (48 GB, 18 CPU); measured with the shipped release binaries of both versions

Summary

The cross-file LSP pass regressed 16.6x between v0.9.0 and v0.10.5 — from 21.5 s to ~358 s on a Java corpus — and it accounts for roughly 78% of the total java indexing regression. It contributes 25,885 edges, about 0.5% of the graph, so the cost/benefit is roughly 14 ms per edge.

Measurement

Corpus: 46,477-file Java tree. Shipped binaries, same host, isolated HOME/CBM_CACHE_DIR per run, sequential (no concurrent load).

v0.9.0 v0.10.5
baseline 99.8 s ~530 s
CBM_DISABLE_LSP_CROSS=1 78.3 s ~172 s
cross-LSP pass alone 21.5 s ~358 s (16.6x)
rest of the pipeline 78.3 s ~172 s (2.2x)

Reproducibility: the 0.10.5 cuts were run twice — xlsp-off 175.0 s and 169.1 s; lsp-off 522.0 s and 525.2 s. Baselines 477.1 s (first sweep) and 534.5 s (recheck), so ~10% run-to-run variance, well inside the effect size.

Edge counts barely move, which is what makes the cost hard to justify as-is:

edges
0.10.5 baseline 5,646,309
0.10.5 CBM_DISABLE_LSP_CROSS=1 5,620,424

Note also that CBM_LSP_DISABLED=1 (disabling LSP entirely) barely changes wall time (522 s vs 530 s baseline) — so the cost is specifically the cross-file pass, not per-file LSP.

Reproduction

for cut in baseline xlsp-off; do
  W=$(mktemp -d)
  ENVV=""; [ "$cut" = "xlsp-off" ] && ENVV="CBM_DISABLE_LSP_CROSS=1"
  time env HOME="$W" CBM_CACHE_DIR="$W/.cache" $ENVV ./codebase-memory-mcp cli index_repository \
    --repo-path /path/to/java-corpus --mode full --name "$cut" --persistence true
done

Where to look

src/pipeline/pass_lsp_cross.c gained +628 lines between the tags, and src/pipeline/lsp_resolve.h +774, which is the natural place to start. pipeline.c already labels this "the most expensive phase", and its comment notes the old sequential implementation cost ~520 s on Kubernetes — so the parallel rewrite was supposed to be the cure here.

This may be the same root as the recorded LSP-resolve audit finding (short-name lookups bypassing QN-only buckets, and no negative memoisation), which would explain why a language with many short, heavily-overloaded method names — Java — is hit hardest.

Cross-corpus context

From the same A/B sweep (11 corpora, both versions), java is by far the worst but the regression is broad:

corpus v0.9.0 v0.10.5 ratio
java (46,477 files) 79.5 s 477.1 s 6.0x
csharp (58,656) 444.3 s 1210.8 s 2.7x
typescript (81,397) 20.7 s 52.0 s 2.5x
linux (94,769) 243.8 s 508.5 s 2.1x
go (31,323) 38.4 s 60.2 s 1.6x

Peak RSS moved only +5–15% across all of them, so this is a throughput regression, not a memory one (the memory side is #1654, which is Linux-specific and separate).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions