codebase-memory-mcp v0.3.0 多语言知识库基准测试:35 个语言的真实仓库评测方法、分层结果与源码级验证
本文基于仓库中的基准测试报告 docs/BENCHMARK.md,完整解读 codebase-memory-mcp 针对 35 个编程语言/配置语言、12 类结构查询问题的评测方法、分层分级(Tier)结果与 Linux 内核级压力测试,并结合当前仓库的 MCP 工具定义(src/mcp/mcp.c)、Cypher 解析器(src/cypher/cypher.c)与 PHP 混合 LSP 实现(internal/cbm/lsp/php_lsp.c)验证报告结论的落地位置。读完后你能掌握:如何复现该语言级基准、如何解读 Tier 分级与 PARTIAL 扣分模式,以及哪些已知限制在当前源码中已有对应的改进路径。
一、基准测试方法论(Methodology)
报告头部声明了 v0.3.0 版本语言基准的五项核心设定,这一套方法论决定了所有后续数据如何解读:
- 覆盖范围:方法部分声明 63 种语言(27 种编程语言 + 8 种配置/标记语言),每种 12 道题(配置类语言 4 道);实际进入汇总统计的得分为 35 种语言(见后文"汇总统计"一节,以报告自身数据为准);
- 重试策略:每题最多 5 次尝试,且采用逐级升级的重试策略(第一次失败后换更具体的查询方式再试);
- 测试对象:全部为真实开源仓库,规模为中型到大型,节点数区间约 78 至 49K;
- 评分规则:PASS(1.0 分)/ PARTIAL(0.5 分)/ FAIL(0.0 分),N/A 不计入分母;
- 测试平台:Apple M3 Pro,macOS Darwin 25.3.0;
- 测试日期:2026-03-01。
需要说明的前提:该报告是 v0.3.0 时间点的快照,当前仓库源码已经历多轮迭代(例如 README 已宣称 162 种语言、15 个 MCP 工具、Hybrid LSP 覆盖 10 种语言),因此报告中列出的"已知限制"部分可能已在新版本中被修复,本文在相应位置会用当前源码做交叉验证。
12 道标准题
每题映射到一个(组)MCP 工具,这套题库本身可以视为"代码智能体对知识图谱应能完成的最低能力集":
| # | 类别 | 问题 | 主要 MCP 工具 |
|---|---|---|---|
| Q1 | 索引 | 验证索引统计(节点、边、模式) | get_graph_schema |
| Q2 | 发现 | 查找函数/方法 | search_graph(label="Function") |
| Q3 | 发现 | 查找类/结构体 | search_graph(label="Class") |
| Q4 | 模式 | 按名称模式查找 | search_graph(name_pattern="...") |
| Q5 | 代码 | 获取代码片段 | get_code_snippet |
| Q6 | 搜索 | 代码文本搜索 | search_code |
| Q7 | 追踪 | 出站调用追踪 | trace_call_path(direction="outbound") |
| Q8 | 追踪 | 入站调用追踪 | trace_call_path(direction="inbound") |
| Q9 | 图谱 | Cypher CALLS 查询 | query_graph |
| Q10 | 富化 | 参数/返回值/属性 | query_graph |
| Q11 | OOP | 继承/实现关系 | query_graph |
| Q12 | 文件 | 列出文件与目录 | list_directory |
配置/标记类语言(HTML、CSS、SCSS、YAML、TOML、HCL、SQL、Dockerfile)只运行 Q1、Q4、Q6、Q12 四题,其余标记 N/A。
12 道题在当前源码中的落点
报告中的工具名可以在当前代码里一一对应到处理函数(均位于 src/mcp/mcp.c):
| 报告工具名 | 当前源码处理函数 |
|---|---|
get_graph_schema |
handle_get_graph_schema |
query_graph |
handle_query_graph |
trace_call_path |
handle_trace_call_path,且 mcp.c#L12350-L12351 中 trace_path 与旧名 trace_call_path 共用同一 handler,说明工具经历了改名,旧名作为兼容别名保留 |
get_code_snippet |
handle_get_code_snippet |
search_code |
handle_search_code |
另外,当前源码中 mcp.c#L31 定义了 MCP_SNIPPET_MAX_LINES = 500(get_code_snippet 的行数上限),这与报告中"bash run 函数一次返回 142 行源码"等 Q5 结果在量级上是自洽的。
二、总览汇总表(35 语言)
以下为报告"Summary Table"的完整数据(SQL 一行的节点/边数取自其分语言明细,汇总表原文该行列错位已按明细修正):
| # | 语言 | 仓库 | 节点数 | 边数 | 得分 | 百分比 | Tier |
|---|---|---|---|---|---|---|---|
| 1 | Lua | neovim/neovim | 23,955 | 90,247 | 12/12 | 100% | 1 |
| 2 | Kotlin | ktorio/ktor | 25,297 | 71,498 | 12/12 | 100% | 1 |
| 3 | C++ | nlohmann/json | 5,262 | 8,681 | 12/12 | 100% | 1 |
| 4 | Perl | mojolicious/mojo | 3,287 | 4,182 | 12/12 | 100% | 1 |
| 5 | Objective-C | AFNetworking | 1,087 | 1,348 | 12/12 | 100% | 1 |
| 6 | Groovy | spockframework/spock | 14,081 | 34,557 | 12/12 | 100% | 1 |
| 7 | C | jqlang/jq | 1,330 | 3,923 | 11/11 | 100% | 1 |
| 8 | Bash | bats-core/bats-core | 436 | 479 | 10/10 | 100% | 1 |
| 9 | Zig | zigtools/zls | 2,824 | 10,230 | 10/10 | 100% | 1 |
| 10 | Swift | Alamofire/Alamofire | 3,631 | 7,639 | 10.5/11 | 95% | 1 |
| 11 | CSS | animate-css/animate.css | 295 | 214 | 4/4 | 100% | 1 |
| 12 | YAML | kubernetes/examples | 2,110 | 1,844 | 4/4 | 100% | 1 |
| 13 | TOML | rust-lang/cargo | 16,773 | 51,403 | 4/4 | 100% | 1 |
| 14 | HTML | twbs/bootstrap | 2,726 | 4,135 | 4/4 | 100% | 1 |
| 15 | SCSS | twbs/bootstrap | 2,726 | 4,135 | 4/4 | 100% | 1 |
| 16 | HCL | hashicorp/terraform | 78 | 76 | 4/4 | 100% | 1 |
| 17 | Dockerfile | docker-library/official-images | 1,481 | 1,588 | 4/4 | 100% | 1 |
| 18 | Python | django/django | 49,398 | 196,022 | 10.5/12 | 87% | 2 |
| 19 | TypeScript | nestjs/nest | 9,063 | 15,772 | 10.5/12 | 87% | 2 |
| 20 | TSX | shadcn-ui/ui | 29,755 | 41,883 | 10.5/12 | 87% | 2 |
| 21 | Go | codebase-memory-mcp(自评) | 2,259 | 6,561 | 10.5/12 | 87% | 2 |
| 22 | Rust | BurntSushi/ripgrep | 4,118 | 6,971 | 10.5/12 | 87% | 2 |
| 23 | Java | spring-projects/spring-petclinic | 660 | 1,080 | 10.5/12 | 87% | 2 |
| 24 | R | tidyverse/dplyr | 1,618 | 2,409 | 10.5/12 | 87% | 2 |
| 25 | Dart | felangel/bloc | 5,089 | 6,430 | 10.5/12 | 87% | 2 |
| 26 | JavaScript | lodash/lodash | 244 | 405 | 9.5/11 | 86% | 2 |
| 27 | Erlang | ninenines/cowboy | 3,270 | 9,815 | 9.5/11 | 86% | 2 |
| 28 | Elixir | elixir-plug/plug | 870 | 865 | 9.5/11 | 86% | 2 |
| 29 | Scala | playframework/playframework | 19,627 | 43,764 | 9/12 | 75% | 2 |
| 30 | Ruby | sinatra/sinatra | 1,377 | 1,893 | 9/12 | 75% | 2 |
| 31 | PHP | laravel/framework | 38,644 | 161,242 | 9/12 | 75% | 2 |
| 32 | C# | jasontaylordev/CleanArchitecture | 1,043 | 1,632 | 9/12 | 75% | 2 |
| 33 | SQL | flyway/flyway | 10,149 | 23,222 | 4.5/6 | 75% | 2 |
| 34 | OCaml | ocaml/dune | 11,691 | 10,447 | 8/11 | 72% | 3 |
| 35 | Haskell | PostgREST/postgrest | 2,066 | 2,463 | 7.5/12 | 62% | 3 |
一个值得注意的自指标题:Go 一行使用的是"codebase-memory-mcp (self)"自评仓库(internal/store/store.go、cmd/、go.mod 结构)。从当前仓库的源码结构看,项目主体已迁移为 C 实现(src/、internal/cbm/),可以推断该自评条目来自项目早期的 Go 版本,这恰好说明基准是"随版本滚动复测"的。
三、Tier 分层规则
报告按得分百分比将语言划入三档:
| Tier | 区间 | 数量 | 语言 |
|---|---|---|---|
| Tier 1 — Excellent | ≥ 90% | 17 | Lua、Kotlin、C++、Perl、Objective-C、Groovy、C、Bash、Zig、Swift、CSS、YAML、TOML、HTML、SCSS、HCL、Dockerfile |
| Tier 2 — Good | 75%–89% | 16 | Python、TypeScript、TSX、Go、Rust、Java、R、Dart、JavaScript、Erlang、Elixir、Scala、Ruby、PHP、C#、SQL |
| Tier 3 — Functional | < 75% | 2 | OCaml(72%)、Haskell(62%) |
分层结论的实用含义:Tier 1 意味着"12 道题全对或仅剩 N/A";Tier 2 普遍只失分在 Q10(属性富化)与个别 Trace 题上;Tier 3 的 OCaml/Haskell 失分集中在调用追踪与继承建模,属于语言范式层面的差异(见第六节跨语言发现)。
四、重点语言逐题明细
以下逐题表格完整继承报告中的分语言明细。表中 Attempts 列为"成功所需尝试次数 / 上限 5",可反映各题的"首次命中率"——绝大多数 PASS 都是 1/5 一次通过,说明工具输出的确定性较好。
4.1 Python(django/django,49,398 节点 / 196,022 边)
| Q# | 问题 | 评级 | 尝试 | 方法 | 备注 |
|---|---|---|---|---|---|
| Q1 | 索引统计 | PASS | 1/5 | get_graph_schema | 49,398 节点、196,022 边、12 个标签、20 种关系类型 |
| Q2 | 查找函数 | PASS | 1/5 | search_graph(Function) | render_to_string(in=1458)、skipUnlessDBFeature、call_command,共 1005 个 |
| Q3 | 查找类 | PASS | 1/5 | search_graph(Class) | ModelAdmin(in=511)、ValidationError(in=415)、ImproperlyConfigured,共 1005 个 |
| Q4 | 模式搜索 | PASS | 1/5 | search_graph(name_pattern=test) | SimpleTestCase、TestCase、SchemaTests,共 22,135 个 |
| Q5 | 代码片段 | PASS | 1/5 | get_code_snippet | render_to_string:django/template/loader.py:52-62 的 11 行 |
| Q6 | 文本搜索 | PASS | 1/5 | search_code(TODO|FIXME) | 5 处命中:admin/checks.py 的 FIXME、admin/options.py 的 TODO |
| Q7 | 出站追踪 | PASS | 1/5 | trace_call_path(outbound) | 21 条边、3 跳:render_to_string -> render、get_template、select_template |
| Q8 | 入站追踪 | PASS | 1/5 | trace_call_path(inbound) | 3 个调用者:test_include、test_include_state、test_include_cache |
| Q9 | Cypher CALLS | PASS | 3/5 | query_graph 带 project 参数 | 前 2 次尝试需要调整 project 参数 |
| Q10 | 属性富化 | PARTIAL | 3/5 | query_graph(properties) | 函数返回了但所有 properties 为 null |
| Q11 | 继承 | PASS | 3/5 | query_graph(INHERITS) | 200 行(触发上限):LazySettings、SimpleAdminConfig、ModelAdmin |
| Q12 | 目录列表 | PASS | 1/5 | list_directory | 21 个条目:django/、docs/、tests/、extras/、pyproject.toml |
得分:10.5/12(87%)。唯一扣分点即 Q10:函数节点存在,但参数/返回类型属性为空——这是全基准最高频的扣分模式(见第六节)。
4.2 JavaScript(lodash/lodash,244 节点 / 405 边)
| Q# | 问题 | 评级 | 尝试 | 方法 | 备注 |
|---|---|---|---|---|---|
| Q1 | 索引统计 | PASS | 1/5 | get_graph_schema | 244 节点、405 边、7 个标签 |
| Q2 | 查找函数 | PASS | 1/5 | search_graph(Function) | build(7 个变体)、baseConvert、Hash,共 36 个 |
| Q3 | 查找类 | PASS | 2/5 | search_graph(Module) | 无 Class 节点(函数式库);回退到 Module:39 个 |
| Q4 | 模式搜索 | PASS | 1/5 | search_graph(name_pattern=test) | browser-testing.yml、markdown-doctest-setup.js,共 10 个 |
| Q5 | 代码片段 | PASS | 1/5 | get_code_snippet | build:lib/main/build-site.js 的 57 行 |
| Q6 | 文本搜索 | PASS | 1/5 | search_code(TODO) | 1 处:.github/workflows/ci-bun.yml |
| Q7 | 出站追踪 | PASS | 2/5 | trace_call_path(baseConvert) | 2 条边:baseAry、自递归 |
| Q8 | 入站追踪 | PASS | 1/5 | trace_call_path(inbound) | 1 个调用者:build-dist.js 模块 |
| Q9 | Cypher CALLS | PASS | 1/5 | query_graph | 5 行:minify->minify、build-dist.js->build |
| Q10 | 属性富化 | PARTIAL | 1/5 | query_graph(properties) | 函数返回但 properties 为 null |
| Q11 | 继承 | N/A | -- | -- | 纯函数式库,无类/继承 |
| Q12 | 目录列表 | PASS | 1/5 | list_directory | 19 个条目:dist/、fp/、lib/、test/、lodash.js |
得分:9.5/11(86%)。该案例展示了"无类语言"的降级路径:Q3 从 Class 标签回退到 Module 标签仍可给分。
4.3 C++(nlohmann/json,5,262 节点 / 8,681 边)
| Q# | 问题 | 评级 | 尝试 | 方法 | 备注 |
|---|---|---|---|---|---|
| Q1 | 索引统计 | PASS | 1/5 | get_graph_schema | 2,456 函数、649 方法、603 宏、153 类 |
| Q2 | 查找函数 | PASS | 1/5 | search_graph(Function) | result(in=99)、push_back(in=42)、CAPTURE(in=35) |
| Q3 | 查找类 | PASS | 1/5 | search_graph(Class) | Fuzzer(out=54)、MutationDispatcher(out=36),共 153 个 |
| Q4 | 模式搜索 | PASS | 1/5 | search_graph(name_pattern=test) | 234 个测试相关节点 |
| Q5 | 代码片段 | PASS | 1/5 | get_code_snippet | result:unit-bjdata.cpp:2935-2936 |
| Q6 | 文本搜索 | PASS | 1/5 | search_code(TODO) | binary_reader.hpp、json.hpp 中 3 个 TODO |
| Q7 | 出站追踪 | PASS | 1/5 | trace_call_path(push_back) | 经由 json_pointer 链的递归调用 |
| Q8 | 入站追踪 | PASS | 1/5 | trace_call_path(push_back) | 23 个调用者:main、sax_event_consumer、lexer、binary_reader |
| Q9 | Cypher CALLS | PASS | 1/5 | query_graph | main->at、main->back |
| Q10 | 属性富化 | PASS | 1/5 | query_graph(properties) | 返回 5 个函数 |
| Q11 | 继承 | PASS | 1/5 | query_graph(INHERITS) | 21 个结果:parse_error、invalid_iterator、type_error、out_of_range |
| Q12 | 目录列表 | PASS | 1/5 | list_directory | 20 个条目:include/、tests/、docs/、CMakeLists.txt |
得分:12/12(100%)。C++ 是少数 Q10 全过的语言之一,说明其属性提取(参数/返回类型)管道对 C++ 已完整落地。
4.4 Rust(BurntSushi/ripgrep,4,118 节点 / 6,971 边)
| Q# | 问题 | 评级 | 尝试 | 方法 | 备注 |
|---|---|---|---|---|---|
| Q1 | 索引统计 | PASS | 1/5 | get_graph_schema | 689 函数、2,039 方法、294 类、70 枚举 |
| Q2 | 查找函数 | PASS | 1/5 | search_graph(Function) | matcher(in=133)、args(119)、printer_contents(72),共 689 个 |
| Q3 | 查找类 | PASS | 1/5 | search_graph(Class) | HiArgs(out=93)、LowArgs(out=74)、Debug(in=54),共 294 个 |
| Q4 | 模式搜索 | PASS | 1/5 | search_graph(name_pattern=test) | test 方法(in=524)、SearcherTester、TestCommand,共 134 个结果 |
| Q5 | 代码片段 | PASS | 1/5 | get_code_snippet | matcher():test_matcher.rs:8-10 |
| Q6 | 文本搜索 | PASS | 1/5 | search_code(TODO) | globset、gitignore、overrides 中 3 个 TODO |
| Q7 | 出站追踪 | PASS | 1/5 | trace_call_path(search) | 12 个被调方:quit_after_match、sort、haystack_builder、search_worker |
| Q8 | 入站追踪 | PASS | 1/5 | trace_call_path(search) | 被 run、main、search_parallel、files_parallel 调用 |
| Q9 | Cypher CALLS | PASS | 1/5 | query_graph | main->set_git_revision_hash、main->set_windows_exe_options |
| Q10 | 属性富化 | PASS | 1/5 | query_graph(properties) | 返回 5 个函数 |
| Q11 | 继承 | PARTIAL | 1/5 | query_graph(INHERITS) | 仅 1 个结果:NoCaptures;Rust trait 未建模为继承 |
| Q12 | 目录列表 | PASS | 1/5 | list_directory | 20 个条目:crates/、tests/、benchsuite/、Cargo.toml |
得分:10.5/12(87%)。Rust 的 PARTIAL 出现在 Q11 而非 Q10,属于"范式差异"扣分:trait 实现关系没有落成 INHERITS 边,这与第六节"已知限制"第 3 条(OCaml functor 间接引用、OCaml/Haskell 调用分析受限)同源。
4.5 PHP(laravel/framework):混合 LSP 深度案例
PHP 是报告中信息量最大的分语言章节,因为它同时是一次"通过 LSP 提升图谱精度"的实证。报告声明(Phase 4–5 PHP-LSP 之后):
- 节点 39,767;边 148,440(基线 196,979,下降 25%);
- CALLS 边 47,341(基线约 83K,名称回退误路由下降 43%);
- 278 个 PHP-LSP 单元测试全部通过(当时项目总数 3,091 / 0 失败);
- LSP 模块规模:约 3,700 行 C 解析器 + 约 700 行标准库 + 约 5,500 行测试 ≈ 9,900 行。
PHP 走的是一条"Light Semantic Pass"(报告中指明文件为 internal/cbm/lsp/php_lsp.c,约 3,500 行),在进程内、无 PHP 运行时的前提下逼近 phpactor 级别的类型解析。当前仓库中该文件实际为 internal/cbm/lsp/php_lsp.c(约 4,600 行),配套测试 tests/test_php_lsp.c(约 5,600 行),规模与报告描述的迭代节奏一致。报告列出的 Phase 4 能力清单:
- 接收者类型追踪,含完整祖先链遍历(带环检测,上限 32 跳);
- 命名空间 +
use子句解析(类、函数、常量),包括包裹与裸两种形态的as别名; - PHPDoc
@var/@param/@property/@method解析,支持泛型(Collection<User>、array<int, User>); - 类型收窄:
instanceof、is_string/int/array/...、assert(...)的顺序收窄,以及 early return / throw 后的负向收窄; - 属性类型追踪:typed 声明、构造函数属性提升、构造函数体内推断(
$this->bar = $bar); - Trait 扁平化,支持
as别名; - 延迟静态绑定链深度,self / parent / static 区分;
- Match / 三元 / clone / 强转的结果类型求值;
- Foreach 元素类型沿
array<T>与 Iterator 传播; - 魔术方法(
__call/__callStatic→ Facade 分派); - 标准库覆盖:SPL、PSR、DateTime、Throwable、Closure,外加 Eloquent Builder/Model/Collection 链、Symfony HttpFoundation、Carbon 日期方法、PSR-7 with-builders。
归属正确性修复(报告称这是首要指标,详见其引用的 PHP_LSP_PRE_FLIGHT 文档第 6 节):
ConfiguresPrompts.configurePrompts → helpers.value误路由(3 个调用点):已修复——这些带类型接收者的$prompt->value()调用不再路由到全局 helper,验证结果为 0 条误路由边;- 总边数减少约 27,500 条,主要来自"接收者是 vendor(未索引)类型时阻断名称回退边"——用部分召回换精度。
逐题明细(Q2–Q5、Q7、Q9–Q12 与基线一致,变化点如下):
| Q# | 问题 | 评级 | 方法 | 备注 |
|---|---|---|---|---|
| Q6 | 文本搜索 | PARTIAL | search_code | 搜索后端问题,单独立票跟踪 |
| Q8 | 入站追踪 | PARTIAL | trace_call_path(inbound) | 工具侧歧义消解问题,单独立票跟踪 |
| 其余 | — | PASS | — | 与基线一致 |
得分:10/12(83%)。报告给出的解释是:两个剩余 PARTIAL 均非 LSP 问题(分属搜索召回与追踪消歧两个工单);LSP 真正交付的是底层"图谱正确性"收益(collide-set 归属),要达到 Tier 1(≥90%)还需搜索召回与追踪消歧工单落地。
边数下降的机制说明(这是理解整个 LSP 设计哲学的关键一段,原文完整继承):当 LSP 知道接收者有类型、但该接收者类未被索引(例如 Composer vendor 类型如 Laravel\Prompts\Prompt)时,它会发出一条合成的 php_method_typed_unindexed 解析结果,桥接层用它来抑制统一提取器的基于名称的回退边。这个权衡是:牺牲召回(宁可没有边,也不猜测边)换精度(绝不产出错误边),pre-flight 论证认为对图谱正确性而言这是正确的取舍。
测试覆盖(报告原文两处数字):tests/test_php_lsp.c 中 100 个单元测试全部通过(另一处记载为 278 个 PHP-LSP 单元测试、项目总计 2,913 / 0 失败)——两处数字反映不同快照,均指向"LSP 行为有全量回归测试兜底"这一事实,当前仓库中 tests/test_php_lsp.c 的存在可以直接证实。
五、其余语言结果速览
为保持篇幅可控,其余 29 个语言不重复 12 行明细表(完整数据在报告 docs/BENCHMARK.md 中),此处按"得分 + 关键扣分/跳过原因"忠实归纳:
| 语言 | 得分 | 关键点(忠实于原报告) |
|---|---|---|
| Lua(neovim) | 12/12,100% | 全过;Q8 入站追踪结果达 129K 字符落盘保存 |
| Kotlin(ktor) | 12/12,100% | 全过;testApplication(in=1504)等高频符号定位准确 |
| TypeScript(nestjs) | 10.5/12,87% | 仅 Q10 PARTIAL(properties null);Q7 首次选 Injectable 出站为 0,换 Module 后 4 条边 |
| TSX(shadcn-ui/ui) | 10.5/12,87% | 仅 Q10 PARTIAL;Q8 对 cn 追出 558 个调用者 |
| Go(自评) | 10.5/12,87% | 仅 Q10 PARTIAL;Q8 追出 68 个调用者 |
| Java(spring-petclinic) | 10.5/12,87% | Q6 PARTIAL:TODO/FIXME 为 0,"error" 命中 3 处 |
| R(dplyr) | 10.5/12,87% | 仅 Q10 PARTIAL;Q11 通过 C++ 结构体继承(Expander 系)3 行通过 |
| Dart(bloc) | 10.5/12,87% | Q7 PARTIAL:identical 是内建引用,叶节点 0 边(正确行为,但无替代函数可追) |
| JavaScript(lodash) | 9.5/11,86% | 见 4.2 节 |
| Erlang(cowboy) | 9.5/11,86% | Q10 PARTIAL(properties null);Q11 N/A(无类继承);Q8 追出 379 个调用者 |
| Elixir(plug) | 9.5/11,86% | Q8 PARTIAL(入口函数 0 调用者);Q11 N/A(用 protocols/behaviours) |
| Scala(playframework) | 9/12,75% | Q7/Q8 均 PARTIAL:queryString 是抽象方法,无出站;无入站 |
| Ruby(sinatra) | 9/12,75% | Q7/Q8 PARTIAL:Minitest setup 基于 block,无调用边 |
| PHP(laravel) | 10/12,83%(明细表 9/12,75% 入 Tier 2) | 见 4.5 节 |
| C#(CleanArchitecture) | 9/12,75% | Q6 PARTIAL(TODO/FIXME 为 0);Q7 PARTIAL:SendAsync 调用外部 ISender.Send,0 出站 |
| SQL(flyway) | 4.5/6,75% | 仅运行 Q1/Q2/Q3/Q4/Q6/Q12;Q6 PARTIAL:CREATE TABLE 只在文档里出现,未索引真实 SQL DDL |
| OCaml(dune) | 8/11,72% | Q7/Q8 PARTIAL:纯函数 0 被调方 + OCaml 调用分析受限;Q11 N/A(modules/functors) |
| Haskell(postgrest) | 7.5/12,62% | Q7/Q8 PARTIAL:函数组合 f . g . h 不建模为 CALLS,仅显式应用被追踪;Q11 PARTIAL:typeclass 未建模 |
| Objective-C | 12/12,100% | 全过;提取 632 个方法 |
| Swift(Alamofire) | 10.5/11,95% | Q10 PARTIAL:0 个 Variable,属性以 817 个 Field 建模 |
| Perl(mojo) | 12/12,100% | 全过;0 类符合预期(Perl 用 package),491 条 CALLS 边验证 |
| Groovy(spock) | 12/12,100% | 全过;5,876 条 Method->Method CALLS |
| C(jq) | 11/11,100% | Q11 N/A;Q8 入站追踪结果 87K 字符落盘 |
| Bash(bats-core) | 10/10,100% | Q3/Q11 N/A(无类);Q5 一次返回 142 行函数源码 |
| Zig(zls) | 10/10,100% | Q3/Q11 N/A(struct 无继承);Q4 按 resolve 模式命中 57 个 |
| Dockerfile | 4/4,100% | 配置类四题全过 |
| CSS | 4/4,100% | 117 文件、115 模块被索引 |
| YAML | 4/4,100% | 1,235 变量、335 文件、309 模块 |
| TOML(cargo) | 4/4,100% | 16,773 节点的大配置仓库,4 题全过 |
| HCL(terraform) | 4/4,100% | 最小样本(78 节点)仍全过 |
| HTML(bootstrap) | 4/4,100% | 与 SCSS 共享同一 bootstrap 索引 |
| SCSS(bootstrap) | 4/4,100% | 18 个 SCSS 测试文件 |
六、Linux 内核压力测试
除语言横评外,报告还包含一个专门的规模压力测试,用于验证"深度追踪 + 大子图"场景下的稳定性:
- 项目:
linux-kernel,子集drivers/net/ethernet/intel/ - 规模:387 个 C/H 文件,19,993 节点,67,305 边
索引构成:
| 标签 | 数量 |
|---|---|
| Function | 11,546 |
| Class(structs) | 1,851 |
| Method | 1,803 |
| Macro | 1,346 |
| Field | 1,095 |
| Community | 734 |
| Enum | 480 |
| Variable | 461 |
逐题结果(Q11 因 C 语言 N/A,实际 11 题):
| Q# | 问题 | 评级 | 尝试 | 方法 | 备注 |
|---|---|---|---|---|---|
| Q1 | 索引统计 | PASS | 1/5 | get_graph_schema | 14 种节点标签、11 种边类型、20K 节点、67K 边 |
| Q2 | 查找函数 | PASS | 1/5 | search_graph(Function) | e1e_rphy(in=64)、e1e_wphy(in=53),共 11,546 个 |
| Q3 | 查找类 | PASS | 1/5 | search_graph(Class) | nic(in=86)、params(in=59),共 1,851 个 C struct |
| Q4 | 模式搜索 | PASS | 1/5 | search_graph(name_pattern=init|probe) | 715 个匹配:i40e_probe(out=59)、ixgbe_probe(out=43) |
| Q5 | 代码片段 | PASS | 1/5 | get_code_snippet | e1e_rphy:e1000.h:543-546 的 4 行 |
| Q6 | 文本搜索 | PASS | 1/5 | search_code(BUG_ON|WARN_ON|pr_err) | 命中 amt.c、e100.c、e1000_ethtool.c |
| Q7 | 出站追踪(depth=5) | PASS | 1/5 | trace_call_path(outbound) | i40e_probe:结果 129K 字符,超大调用树、无超时 |
| Q8 | 入站追踪(depth=5) | PASS | 1/5 | trace_call_path(inbound) | e1e_rphy:67.6K 字符,64 个直接调用者、深层链 |
| Q9 | Cypher CALLS | PASS | 1/5 | query_graph | 10 条 CALLS 边:netdev_boot_setup、amt 函数族 |
| Q10 | 属性富化 | PARTIAL | 2/5 | query_graph | IS NOT NULL 不受支持,调整后重试成功 |
| Q11 | 继承 | N/A | -- | -- | C 语言 |
| Q12 | 目录列表 | PASS | 1/5 | list_directory | 17 个条目:e100.c、i40e/、ice/、ixgbe/、igb/ |
得分:11/11(100%,Q11 N/A)
压力指标:
| 测试 | 结果 | 规模 | 超时? |
|---|---|---|---|
| 深度追踪(depth=5,outbound,i40e_probe) | PASS | 129,026 字符 | 否 |
| 深度追踪(depth=5,inbound,e1e_rphy) | PASS | 67,600 字符 | 否 |
| 深度追踪(depth=5,both,e1000e_reset) | PASS | 中等 | 否 |
| 多跳 Cypher(3 跳 CALLS 链) | PASS | 10 条有效链 | 否 |
报告结论:工具处理 20K 节点的内核子图无超时;在出度很高(out_degree=59)的 probe 函数上做深度追踪能产出巨大但完整的结果;社区检测识别出 734 个簇,可用于理解驱动模块边界。
源码交叉验证:报告中的 Q10 扣分点"Cypher IS NOT NULL 不受支持"是 v0.3.0 时间点的问题;在当前源码 src/cypher/cypher.c#L1079-L1083 中已经能看到 IS NULL / IS NOT NULL 的词法/语法处理(cypher.c#L2677-L2682 有对应的求值分支),说明该限制在后续迭代中已有实现路径。同理,src/mcp/mcp.c#L472-L504 中 query_graph 的当前工具描述声明了"100k 行硬上限、默认无上限",与报告中"200 行上限"的旧行为不同——报告记录的 200 行上限属于 v0.3.0 时代的默认值(Python Q11、Kotlin Q11 的"200 rows (capped)"正是这一上限的现场证据)。
七、跨语言发现(Cross-Cutting Findings)
优势(Strengths,原文六条完整继承)
- 跨全部 63 个仓库、各种规模(78 到 49K 节点)零索引失败;
- 17 个语言 100% 满分——一半的语言拿到完美分数;
- 没有语言低于 62%——最弱的也能完成核心操作;
- 大型代码库可处理:Django(49K 节点)、Laravel(38K 节点)、neovim(24K 节点),无性能问题;
- 内核级压力测试通过:20K 节点、67K 边、129K 字符的追踪,零超时;
- "已被移除"语言依然强劲:Obj-C(100%)、Perl(100%)、Groovy(100%)、Swift(95%)、Dart(87%)。
常见 PARTIAL 扣分模式
- Q10(属性):多数语言返回的函数
properties=null,参数/返回提取不完整——这是单一最高频扣分点; - Q7/Q8(追踪):抽象方法、入口函数、内建引用正确地返回 0 条边(无假阳性),但被扣为 PARTIAL(当没有替代函数有边时);
- Q11(继承):使用替代范式的语言(traits、protocols、typeclasses、modules)的 INHERITS 边有限。
已知限制(原文六条完整继承)
- 函数属性:多数语言的参数类型与返回类型未提取,导致
properties=null; - Haskell 调用追踪:函数组合(
f . g . h)不建模为 CALLS 边,仅显式函数应用被追踪; - OCaml 调用分析:受模块 functor 间接引用限制;
- Cypher
IS NOT NULL:(v0.3.0 时)Cypher 解析器不支持——如第六节所述,当前 src/cypher/cypher.c 已包含该语法的处理; - Scala/Ruby 追踪:抽象方法与基于 block 的模式可能产生 0 条追踪边;
- query_graph 200 行上限:大代码库上的聚合查询(COUNT)会被静默低估——当前工具描述已演进为 100k 行硬上限(src/mcp/mcp.c#L475-L476)。
八、汇总统计(Aggregate Statistics)
| 指标 | 数值 |
|---|---|
| 测试语言数 | 35 |
| 提问总数 | 370 |
| PASS | 327(88%) |
| PARTIAL | 25(7%) |
| FAIL | 18(5%) |
| N/A(不计分母) | 41 |
| 加权得分 | 339.5 / 370 |
| 总体百分比 | 91.8% |
| 满分语言(100%) | 17 |
| Tier 1(≥90%) | 17 |
| Tier 2(75–89%) | 16 |
| Tier 3(<75%) | 2 |
九、复现与扩展:仓库中可用的基准脚本
仓库自带两个与本报告直接相关的测量脚本,可作为读者自行验证的抓手:
1. search_graph 性能基准 scripts/benchmark-search-graph.sh
用途:对已编译的二进制测量 search_graph 的 name_pattern= 正则/LIKE 预过滤性能,以及 BM25 query= 路径性能。用法:
scripts/benchmark-search-graph.sh <binary-path> <project-name>
# 示例:
scripts/benchmark-search-graph.sh ./build/c/codebase-memory-mcp my-project
脚本内置 8 个测试用例:4 个 name_pattern 用例(.*Controller.*、.*Service.*、.*Repository.*、精确函数名、Method+get 组合),以及 3 个走 BM25 路径的 query= 用例。它通过标准输入向二进制发送 tools/call 的 JSON-RPC 请求(工具名 search_graph),逐用例打印毫秒耗时与返回条数。这对应报告 Q4(模式搜索)的性能维度。
2. 索引基准 scripts/benchmark-index.sh
用于测量整库索引耗时,对应报告"平均仓库毫秒级、Django 49K 节点无性能问题"等结论的测量方式。
工具参数速查(与报告 12 题直接相关的当前工具签名,取自 src/mcp/mcp.c 的工具定义):
| 工具 | 关键参数 | 默认值 |
|---|---|---|
search_graph |
label、name_pattern、file_pattern、include_connected、limit、offset、format |
limit 50,响应带 total 与 has_more 供分页 |
query_graph |
query(Cypher)、max_rows、graph(code/missed) |
无 offset;100k 行硬上限 |
trace_path(别名 trace_call_path) |
function_name、direction(inbound/outbound/both)、depth、limit、mode(calls/data_flow/cross_service)、cursor |
depth 3、limit 100;depth 会经 clamp_mcp_depth 钳制(见 mcp.c#L7016) |
get_code_snippet |
qualified_name、include_neighbors |
行数上限 500(MCP_SNIPPET_MAX_LINES,mcp.c#L31) |
search_code |
pattern、file_pattern、path_filter、mode(compact/full/files)、limit |
limit 10;响应带 total_grep_matches 与 total_results |
十、结论与适用边界
这份 v0.3.0 基准的价值不在于"91.8%"这个总分,而在于它把"代码知识图谱能回答什么"拆成了 12 个可重复、可判分的问题,并在真实开源仓库上给出了逐题证据链:
- 能稳定回答的:索引统计(Q1)、符号发现(Q2/Q3)、名称模式搜索(Q4)、源码取回(Q5)、文本搜索(Q6)、双向调用追踪(Q7/Q8,含 129K 字符级的深追踪)、Cypher 多跳查询(Q9)——这些在内核级子图上也全部无超时;
- 部分语言仍有缺口的:属性富化(Q10,properties null 是最高频扣分)、非 OOP 范式的继承建模(Q11)、以及 Haskell 函数组合/OCaml functor 这类语言特有的调用形态;
- 演进方向可验证:PHP 案例证明"混合 LSP 换精度"的路线(-25% 总边、-43% 误路由)有完整单元测试兜底(tests/test_php_lsp.c),而 Cypher
IS NOT NULL等旧限制在当前 src/cypher/cypher.c 中已见处理逻辑。
适用边界提醒:所有结论基于 2026-03-01 的 v0.3.0 快照与 Apple M3 Pro 平台;当前仓库源码(162 语言、15 工具、10 语言 Hybrid LSP)已领先于该快照,引用具体数字时应以 docs/BENCHMARK.md 的版本标注为准,并用 scripts/benchmark-index.sh 与 scripts/benchmark-search-graph.sh 在本地复测。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00