mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-08 08:53:43 +08:00
perf(lsp): skip cross-LSP for machine-generated files
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).
This commit is contained in:
@@ -1782,6 +1782,31 @@ static void resolve_worker(int worker_id, void *ctx_ptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CBMLanguage lang = rc->files[file_idx].language;
|
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 +
|
/* Cross-file LSP is a per-file tree-sitter re-parse + AST walk +
|
||||||
* registry lookups — ~50-150ms per file. It can ONLY find calls
|
* registry lookups — ~50-150ms per file. It can ONLY find calls
|
||||||
* that exist in the AST. If the per-file extract found zero 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 =
|
bool cross_lsp_eligible =
|
||||||
(rc->all_defs && rc->def_count > 0 && cbm_pxc_has_cross_lsp(lang) &&
|
(rc->all_defs && rc->def_count > 0 && cbm_pxc_has_cross_lsp(lang) &&
|
||||||
result->calls.count > 0 &&
|
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. */
|
/* 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 &&
|
if (result->calls.count == 0 && result->usages.count == 0 && result->throws.count == 0 &&
|
||||||
|
|||||||
Reference in New Issue
Block a user