Rust Glancer:一个将 Rust LSP 的内存占用降低 100 倍的实现

一个新的 Rust 语言服务器 Rust Glancer 试图通过把大部分分析数据卸载到磁盘上、并且只在每次查询时加载所需内容,从而大幅减少 RAM 占用,这与 rust-analyzer 始终驻留内存、完全增量式的模型形成对比。评论者指出,rust-analyzer 在大型工作区中经常会消耗数 GB 内存,并讨论其最初“不要磁盘缓存,强制快速分析”的理念在项目规模和 proc-macro 使用不断增长的今天是否仍然适用。讨论还涉及延迟、索引策略、磁盘格式、未来对 proc 宏和更多编辑器的支持,以及把 LLM 作为编码助手而不是“脑替代品”的谨慎但务实的使用方式。

项目目标与架构

  • Rust Glancer 是一个 Rust 语言服务器,它把大部分分析数据保存在磁盘上,而不是放在 RAM 中。
  • 它会先进行一次完整的、非增量的初始索引,然后只将每次查询所需的数据加载到内存中。
  • 打开的缓冲区会被优先处理;其他内容则在后台完成索引。
  • 在保存时,它只会重新索引受影响的 crate,而不是整个项目;脏缓冲区会在最后一次语义快照之上使用轻量级的语法覆盖层。

内存使用与性能取舍

  • 目标是“对于合理规模的项目,<100 MB”,尽管初始索引阶段短时间内可能比 rust-analyzer(RA)使用更多内存。
  • 峰值成本主要在每个项目首次建立索引时,或当依赖 / 工具链发生变化时才会付出一次。
  • 作为回报,空闲时的资源占用很低,重启成本很小,而且与 RA 始终保持热状态的增量式方法相比,CPU 更凉快。
  • 磁盘上的产物会随着项目规模增长(给出的例子是 Rust Glancer 自身约 225 MB)。

磁盘缓存 vs 增量式内存分析

  • 几位评论者抱怨 RA 可能消耗多个 GiB,甚至十几 GiB 内存,尤其是在多个工作区之间时。
  • 有人认为 RA 应该更积极地使用磁盘(例如 mmap 的结构,或基于 RocksDB 的缓存)。
  • 一段详细回复解释说,RA 早期刻意避免使用磁盘,原因包括:
    • 降低复杂度以及历史 IDE 缓存中出现的损坏问题。
    • 强制实现快速、惰性的内存分析,并获得良好的启动时间。
    • 重点放在原型化 IDE 架构,而不是先做持久化。
  • 提出的“中间路线”是:为依赖项使用紧凑的磁盘索引,再为活动工作区提供一个惰性的、增量式的内存后端,并且当文件变为可编辑时能够切换。

Proc 宏与可扩展性

  • Rust Glancer 计划通过插件 / DSL 实现一种“描述效果,不执行代码”的 proc 宏模型,目标是未来某个版本。
  • 其动机是避免在 LSP 中执行任意代码,同时仍然能够建模对外可见的宏效果。

编辑器支持与用户体验

  • 即将发布的版本计划支持 Neovim 和 Zed;LSP 仍然需要针对每个编辑器做少量适配器。
  • 自动导入和“查找引用”被承认为更重的功能,目前正在进一步优化,之后才会全面启用。

LLM 在开发中的使用

  • 作者把 LLM 当作助手:在领域知识方面有帮助,但在架构方面较弱。
  • 指出的坑包括:倾向于使代码膨胀、重复功能、抗拒重构,以及带着不应有的自信发言。
  • 其他人也分享了正面经验(快速创建简单的 LSP),以及对过度依赖的担忧。

缩写与受众

  • 讨论焦点之一是像“LSP”这样的术语是否应该始终展开说明。
  • 一方观点:应始终解释缩写,以包容更多读者。
  • 另一方观点:在面向程序员的论坛上,Rust/LSP 这类术语通常被认为是默认已知的;如果需要,读者可以自行查找。