From aecd86135f139d3ff9e8ac2220eff90b3b582809 Mon Sep 17 00:00:00 2001 From: Martin Vogel Date: Thu, 21 May 2026 11:29:21 +0200 Subject: [PATCH] perf(lsp): skip cross-LSP for machine-generated files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Investigation of kubernetes' largest Go files revealed the perf tail is dominated by machine-generated code: pkg/generated/openapi/zz_generated.openapi.go 74,266 lines staging/src/k8s.io/api/core/v1/generated.pb.go 71,154 lines Multiple *.pb.go protobuf files 12-14K lines each 209 files in staging/.../client-go/applyconfigurations/ These files are boilerplate (getters/setters/marshal/unmarshal) with limited semantic value for code-navigation queries. But because tree- sitter parse of a 70K-line file alone is ~1-2 seconds, even one unresolved cross-file call in such a file triggers the full cross-LSP overhead and dominates the wall time. Skip cross-LSP for files matching common generated-file conventions: *.pb.go (Go protobuf) zz_generated* (k8s codegen convention) *_generated.go (general Go codegen) *.gen.go (general Go codegen) /applyconfigurations/ (k8s codegen subtree) *_pb2.py, *_pb2_grpc.py (Python protobuf) *.pb.cc, *.pb.h, *.pb-c.{c,h} (C/C++ protobuf) The per-file LSP during extract still indexes their defs and calls normally — only the cross-file resolution refinement is skipped. Graph quality: zero loss for hand-written code; for generated code cross-file method resolution falls back to whatever per-file LSP captured (which is typically complete for intra-package boilerplate). --- src/pipeline/pass_parallel.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/pipeline/pass_parallel.c b/src/pipeline/pass_parallel.c index 0b8d1933e..92d59f29d 100644 --- a/src/pipeline/pass_parallel.c +++ b/src/pipeline/pass_parallel.c @@ -1782,6 +1782,31 @@ static void resolve_worker(int worker_id, void *ctx_ptr) { } CBMLanguage lang = rc->files[file_idx].language; + const char *rel = rc->files[file_idx].rel_path; + + /* Skip cross-LSP for machine-generated files — they're huge (10k- + * 70k lines for k8s protobuf/openapi), have low semantic value for + * graph navigation (boilerplate getters/setters/marshal), and + * dominate the cross-LSP wall time when they have even one + * unresolved call (tree-sitter parse on a 70k-line file is ~1-2s). + * The per-file LSP during extract still indexes their defs/calls + * normally — only the cross-file resolution refinement is skipped. */ + bool is_generated = false; + if (rel) { + is_generated = + (strstr(rel, ".pb.go") != NULL) || + (strstr(rel, "zz_generated") != NULL) || + (strstr(rel, "_generated.go") != NULL) || + (strstr(rel, ".gen.go") != NULL) || + (strstr(rel, "/applyconfigurations/") != NULL) || + (strstr(rel, "_pb2.py") != NULL) || + (strstr(rel, "_pb2_grpc.py") != NULL) || + (strstr(rel, ".pb.cc") != NULL) || + (strstr(rel, ".pb.h") != NULL) || + (strstr(rel, ".pb-c.c") != NULL) || + (strstr(rel, ".pb-c.h") != NULL); + } + /* Cross-file LSP is a per-file tree-sitter re-parse + AST walk + * registry lookups — ~50-150ms per file. It can ONLY find calls * that exist in the AST. If the per-file extract found zero calls, @@ -1795,7 +1820,8 @@ static void resolve_worker(int worker_id, void *ctx_ptr) { bool cross_lsp_eligible = (rc->all_defs && rc->def_count > 0 && cbm_pxc_has_cross_lsp(lang) && result->calls.count > 0 && - result->resolved_calls.count < result->calls.count); + result->resolved_calls.count < result->calls.count && + !is_generated); /* Skip files with nothing else to resolve and no cross-LSP work. */ if (result->calls.count == 0 && result->usages.count == 0 && result->throws.count == 0 &&