Repository navigation
feat: navigate into Maven dependency jars, with less memory - #3
Merged
Merged
Conversation
Names the working tree does not declare now resolve into the project's Maven dependencies, not only the JDK. Measured with the new nav-bench on 1,500 random identifiers per seed: Nacos 98.2-99.3% resolve (JDT LS 98.5-99.5%), 1493-1494 of 1500 to the same place as JDT LS; ruoyi-vue-pro 98.4-98.5% (was about 72%). - internal/deps reads the working tree's pom.xml files with their parents and imported BOMs and follows dependencies through the local repository as Maven mediates them (nearest wins, root management sets versions, test/provided/optional are not transitive, exclusions apply), without running Maven or downloading anything. - Only each jar's directory is listed up front. A class is read the first time a lookup needs it: from the -sources.jar when it was downloaded, else as a stub of signatures written from its class files (member classes, constants, annotation defaults, parameter names from the debug information). Copies go read-only under the state directory. - Sources generated into target/generated-sources and Gradle's build/generated are indexed although .gitignore leaves them out. - String and class literals, Iface.super and Lombok log fields type the calls on them, so "a".trim(), Foo.class.getName(), log.info(...) and Iface.super.m() resolve. - Memory: indexing reuses token and read buffers (198 MB allocated on Nacos down to 86 MB), returns the scan's garbage to the system, and the server runs with GOGC=25 unless GOGC is set (68 MiB footprint down to 47 MiB without dependencies). Library paths are short and keyed by a substring of themselves, so 154,000 dependency classes cost about 20 MiB; with dependencies Nacos ends at 62-69 MiB, ruoyi at 91 MiB (JDT LS: 3 GB). - cmd/nav-bench is the measuring tool behind the README's numbers. --no-dependencies turns dependency jars off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
为什么
上一轮实测:插件在 Nacos 上能跳 95%,ruoyi-vue-pro 只有约 72%。跳不了的大多是依赖库里的声明,比如 Swagger 的
@Schema(description = ...)、Lombok、校验注解、Hutool 和 MyBatis-Plus 的方法。这个 PR 让插件能跳进 Maven 依赖库,同时把内存压下来。改动
跳进 Maven 依赖库(新包
internal/deps)maven.go:读工作区每个pom.xml和它的父 POM、导入的 BOM,再沿本地仓库(~/.m2/settings.xml的localRepository,默认~/.m2/repository)里的 POM 找传递依赖。规则和 Maven 一致:dependencyManagement决定版本;test/provided/可选依赖不传递,exclusions生效;不运行 Maven、不联网,本地仓库没有的 jar 直接跳过。
jars.go:并行列出每个 jar 的目录。某个类第一次被查到时才读取:有-sources.jar就读源码,否则从.class生成签名存根。跳进去时写一份只读副本到${stateDir}/dependency-sources/<坐标>-<jar 身份哈希>/,不写本地仓库,也不写插件包。classfile.go、signature.go、stub.go:读取 class 文件,生成 Java 存根,包括:arg0;java.lang同名的同包类写全限定名。version.go:按 Maven 的规则比较版本,版本是范围、或者引用了不认识的属性时,取本地已有的最高版本。接入(
workspace、codenav、lsp、main)pom.xml变了、或距上次读取超过 5 分钟,就重新读取。JDK 和依赖合成一个库,同一个类出现多次时取第一个:JDK 在前,依赖按 classpath 顺序。codenav.Library:库路径可以是<jar 编号>!a/b/C.java。类名索引的键改成路径的子串,去掉了srcs表,15 万个类时少占约 10 MiB。--no-dependencies开关,可以关掉依赖库跳转。其他命中率改进
target/generated-sources、target/generated-test-sources和 Gradle 的build/generated也进索引,即使被.gitignore忽略(JDT LS 也会索引这些)。Iface.super.m()、Lombok 日志注解生成的log字段(@Slf4j对应org.slf4j.Logger)都能推出类型,后面的调用能继续跳。内存
debug.FreeOSMemory)。GOGC=25(用户设置了GOGC时以用户为准)。不带依赖时,Nacos 跑完实测从 68 MiB 降到 47 MiB,延迟只多 0.01 ms。工具与文档
cmd/nav-bench:README 里的数字都是用它测的。对真实项目随机取标识符,测命中率、延迟和内存,可以同时测 JDT LS。docs/releases/v0.0.1.md(0.0.1 还没发布)、codenav/UPSTREAM.md和doc.go。.gitattributes,让测试数据在 Windows 上按原字节检出。实测(Apple M4,各 1500 个随机位置)
测试
go test ./...和go test -race ./...全部通过。super、log推断,以及同名类取第一个。不在本 PR
list.get(i).split()、比较器里的o1.getX()、v -> v.getVersion()。🤖 Generated with Claude Code