rust-glancer: An alternative LSP for Rust with focus on low memory usage

rust-glancer: An alternative LSP for Rust with focus on low memory usage

rust-glancer:一款专注于低内存占用的 Rust LSP 替代方案

I want to present a project that I’ve been working on for the past 4 months: an alternative Rust LSP implementation that is built with a focus on low memory usage. It has two main features: It can use very little memory (target <100mb for reasonable projects). There are caveats, these are described below. It allows immediate indexing after restart: if your project was indexed, restarting the editor will not require re-indexing. 我想介绍一个我过去 4 个月一直在开发的项目:一个专注于低内存占用的 Rust LSP 实现。它有两个主要特点:内存占用极低(目标是在处理常规项目时低于 100MB)。当然,这有一些限制,下文会详细说明。它支持重启后立即索引:如果你的项目已经完成过索引,重启编辑器后无需重新索引。

These features make Rust Glancer suitable for the older computers: I have tested it on my old MacBook Pro M1 2020 with 8GB RAM, and it was pretty good. 这些特性使得 Rust Glancer 非常适合老旧电脑:我在我那台 8GB 内存的 2020 款 MacBook Pro M1 上进行了测试,效果相当不错。

MachineLSPBase indexing (engine usable)Full indexing
MacBook Pro M4 Max, 36GB (2025)Rust Glancer5 seconds8 seconds
MacBook Pro M4 Max, 36GB (2025)rust-analyzer6 seconds13 seconds
MacBook Pro M1, 8GB (2020)Rust Glancer6 seconds9 seconds
MacBook Pro M1, 8GB (2020)rust-analyzer7 seconds14 seconds

As you can imagine, 4 months is not a lot of time for a project as big as a Rust LSP. Rust Glancer is not a complete LSP yet, it has a lot of missing functionality, it has some known bugs, and it has a lot of things I want to improve. At the same time, it is already pretty capable: it has a full indexing pipeline with type inference and a trait solver (chalk), most of the “normal” Rust syntax is supported, and most of the “normal” LSP actions do work as well: goto definition, hover, inlay hints, completions, you name it. 可以想象,对于像 Rust LSP 这样庞大的项目来说,4 个月的时间并不算长。Rust Glancer 目前还不是一个完整的 LSP,它缺失了很多功能,存在一些已知 Bug,还有很多地方需要改进。但与此同时,它已经具备了相当的能力:它拥有完整的索引流水线,包含类型推断和 trait 解析器(chalk),支持大多数“常规” Rust 语法,并且大多数“常规” LSP 操作也能正常工作:跳转到定义、悬停提示、内联提示、代码补全等等,应有尽有。

If you are interested, you can already try it out: just install the VS Code extension here, or, if you prefer, build and install the vsix from the repository. The rest of the post contains the history of the project: motivation, LLM use, plans and roadmap. If you’re not interested, you might want to check out the project documentation instead. 如果你感兴趣,现在就可以尝试一下:只需在此处安装 VS Code 插件,或者如果你愿意,也可以从仓库构建并安装 vsix 文件。本文的其余部分包含了该项目的历史:动机、LLM 的使用、计划和路线图。如果你不感兴趣,也可以直接查看项目文档。

Difference with rust-analyzer

与 rust-analyzer 的区别

There are several reasons why rust-analyzer consumes a lot of memory: rust-analyzer 占用大量内存有几个原因:

  1. Rust workspaces genuinely have a lot of information that must be indexed: thousands of functions, structures, traits, relationships between these, function bodies and statements in them, etc. Each of these needs to be analyzed and remembered, and you can’t really cheat if you want to have things like “find all references to this structure”.

  2. Rust 工作区确实有大量信息需要索引:成千上万的函数、结构体、trait、它们之间的关系、函数体及其内部语句等。每一项都需要被分析和记忆,如果你想要实现“查找该结构体的所有引用”这类功能,是无法投机取巧的。

  3. rust-analyzer uses salsa as its database. It’s an incremental query-based database, which lazily computes all the data you need without having to explicitly “record” everything. It is a very cool approach, but it’s inherently tied to memory, which makes it hard to move parts of data from memory elsewhere.

  4. rust-analyzer 使用 salsa 作为其数据库。这是一个基于增量查询的数据库,它会懒加载计算你所需的所有数据,而无需显式地“记录”一切。这是一种非常酷的方法,但它本质上与内存绑定,这使得很难将部分数据从内存转移到其他地方。

  5. rust-analyzer uses rowan for syntax tree representation. The cool property here is that it allows partial invalidation: if only a part of the file changed, only the relevant bits have to be reparsed, which makes it faster than having to re-parse the whole file on each keystroke. However, the tree-like representation inside of it can cause heavy memory fragmentation (meaning that the amount of RAM taken from the OS is higher than the amount of “actually used” RAM).

  6. rust-analyzer 使用 rowan 进行语法树表示。其酷炫之处在于它允许部分失效:如果文件只有一部分发生了变化,只需重新解析相关部分,这比每次按键都重新解析整个文件要快得多。然而,其内部的树状表示可能会导致严重的内存碎片(意味着从操作系统占用的内存量高于“实际使用”的内存量)。

(1) is something we have to live with (though there are a few optimizations we can do there which Rust Glancer does), but (2) and (3) are the consequences of the rust-analyzer architecture. rust-analyzer chose them to make the LSP faster, and it does work for that purpose. (1) 是我们必须接受的现实(尽管我们可以做一些优化,Rust Glancer 已经做了),但 (2) 和 (3) 是 rust-analyzer 架构带来的后果。rust-analyzer 选择这些架构是为了让 LSP 更快,而且它确实达到了目的。

The idea I had when I started the project: what if we don’t try to make an incremental LSP? What if all we have is a frozen analysis result that gets invalidated on save? It obviously will not be as fast as rust-analyzer, but it will give us the properties we seek: analysis results can be offloaded to the filesystem and loaded to memory only when they are actually needed. 我在启动这个项目时的想法是:如果我们不尝试做一个增量式 LSP 会怎样?如果我们只保留一个在保存时才会失效的“冻结”分析结果呢?它显然不会像 rust-analyzer 那样快,但它能提供我们想要的特性:分析结果可以卸载到文件系统中,仅在真正需要时才加载到内存中。

Saved analysis is reusable, and since it’s already offloaded to the filesystem, it can be reused after the editor restart. This is the core idea of Rust Glancer. It indexes the workspace once and preserves results in the filesystem, and then whenever queries need something, they can load the required information for the duration of the query. 保存的分析结果是可重用的,而且由于它已经卸载到文件系统中,因此在编辑器重启后可以继续使用。这就是 Rust Glancer 的核心思想。它对工作区进行一次索引并将结果保存在文件系统中,然后每当查询需要信息时,它们可以在查询期间加载所需的信息。

It doesn’t come for free though: frozen workspace analysis is slower than lazy incremental by definition, since loading and deserializing data from filesystem is slower than loading from memory. To mitigate that, Rust Glancer has to use some tricks: for example, when you type, it doesn’t perform full blown analysis on each keystroke, it instead attempts shallow analysis of the current body and reuses the previous complete index. 但这并非没有代价:从定义上讲,冻结工作区分析比懒增量分析要慢,因为从文件系统加载和反序列化数据比从内存加载要慢。为了缓解这个问题,Rust Glancer 必须使用一些技巧:例如,当你输入时,它不会在每次按键时执行完整的分析,而是尝试对当前代码块进行浅层分析,并重用之前的完整索引。

This makes completions reasonably fast, but it also means that new items (imports, structures, traits) are not “indexed” until you save the document. Which, hopefully, should not be a problem: you really get used to it fast, and at least in my case it does not feel overly wrong after a while. If that sounds scary, I suggest to just try it, it really is not. 这使得代码补全速度相当快,但也意味着新项目(导入、结构体、trait)在保存文档之前不会被“索引”。希望这不会成为问题:你很快就会习惯它,至少对我来说,过了一段时间后并不会觉得有什么不妥。如果这听起来很可怕,我建议你亲自试一试,其实真的没那么糟。

For people who rely on agentic workflows, Rust Glancer is also optimized for large amount of out-of-editor changes. I’m not sure why, but in rust-analyzer I’ve observed that when agents edit the code, inlay hints can get out of place, and I had the same problem in Rust Glancer initially, but it was resolved by implementing a custom file watcher and tweaking it somewhat. The server also has lower priority for out-of-editor changes, so agentic changes do not cause rapid re-indexing. 对于依赖智能体(Agentic)工作流的人来说,Rust Glancer 也针对大量的编辑器外文件变更进行了优化。我不确定原因,但在 rust-analyzer 中我观察到,当智能体编辑代码时,内联提示可能会错位。Rust Glancer 最初也有同样的问题,但通过实现自定义文件监视器并进行了一些调整后,问题得到了解决。服务器对编辑器外变更的优先级也较低,因此智能体的变更不会导致频繁的重新索引。

Still, it’s important to understand that Rust Glancer has some benefits, but also has some drawbacks (besides being incomplete, obviously) compared to rust-analyzer. Maybe I will manage to solve some of them eventually, but it’s highly unlikely that Rust Glancer will ever become “just like rust-analyzer, but better”. I imagine that rust-analyzer will remain the default choice for projects that care about completeness and keystroke accuracy, while Rust Glancer will work for people with weaker machines or people who are ready for some sacrifices to reduce RAM usage. 尽管如此,必须明白 Rust Glancer 与 rust-analyzer 相比既有优势,也有劣势(显然,除了它尚未完成之外)。也许我最终能解决其中一些问题,但 Rust Glancer 极不可能成为“和 rust-analyzer 一样好,甚至更好”的工具。我认为,对于注重完整性和按键准确性的项目,rust-analyzer 仍将是首选,而 Rust Glancer 则适合那些机器性能较弱,或者愿意为了降低内存占用而做出一些牺牲的用户。