内存
Rspack 可以在构建和 HMR 更新时采集内存快照。反馈内存问题时,请收集这些文件,帮助维护者调查问题。
普通用户
启用分析
请使用该版本或更高版本的 debug 或 profiling 包(标准 release 包不含 allocative 支持)。快照采集默认关闭,需要在运行项目时设置 RSPACK_ALLOCATIVE_DIR,开启采集并指定输出目录。
直接使用 Rspack
如果项目直接依赖 @rspack/core,将其替换为相同版本的 debug 包。例如,将 2.3.0 改为 npm:@rspack-debug/[email protected]:
保留依赖原本所在的字段(dependencies 或 devDependencies),然后执行 pnpm install。
通过 Rsbuild 等框架使用 Rspack
如果项目通过 Rsbuild 等框架间接使用 Rspack,需要通过包管理器的 override 覆盖 @rspack/core。使用 pnpm 时,在 package.json 中添加以下配置:
版本号应与框架实际使用的 @rspack/core 版本一致(本例为 2.3.0),然后执行 pnpm install。关于诊断包覆盖的更多说明,请参阅调试指南。
两种方式也都可以使用 profiling 构建的包替代 debug 包。运行项目原有的构建或 dev 命令时,设置 RSPACK_ALLOCATIVE_DIR 即可。不设置该变量时,不会采集快照。如果没有合适的包,可以参考构建本地 binding,从源码构建。
采集内存快照
采集构建快照
使用项目原有的构建命令,并设置一个绝对输出目录:
请确认构建、配置文件及插件都加载了预期的诊断包。对于集成 Rspack 的框架,保留框架原有的构建命令,并使用版本兼容的诊断包覆盖。
首次构建完成后,输出目录中会生成以下文件:
每个进程应使用新的目录。同一进程内的多个 compiler 共用快照编号,新进程会重新编号;多个进程共用目录可能覆盖文件。
采集 HMR 更新
启动 dev server 时,设置相同的输出变量:
修改源文件,并等待每次重建完成。单个 compiler 在完成三次重建后,会生成四份字节快照:
每份快照都有对应的 counts、metadata 和 warnings 文件。使用相同包的 watch 模式构建,同样支持通过 RSPACK_ALLOCATIVE_DIR 采集快照。
复现问题时,请保持项目原有的构建模式和 sourcemap 设置,并记录每次 HMR 更新的修改内容。
上传问题反馈数据
构建或需要复现的 HMR 更新完成后,将整个输出目录压缩打包,并作为附件上传到问题反馈中。每份快照都需要包含以下四类文件:
例如,打包构建快照目录:
反馈 HMR 问题时,请打包从首次构建到最后一次相关重建的完整序列,包含每份快照的配套文件。保留原始文件名,方便维护者匹配快照及其附加文件。
问题反馈中还应包含以下信息:
- Rspack 和诊断包版本、Node.js 版本及操作系统。
- 采集时使用的命令、配置、构建模式和 sourcemap 设置。
- 复现项目或复现步骤;对于 HMR,还需要说明修改内容及顺序。
- 观察到的内存问题、出现时机和构建日志。如果未生成快照,也请说明情况,并附上命令和日志。
开发者章节介绍了如何检查这些数据。
Rspack 开发者
使用 allocative skill
Rspack 仓库提供了 rspack-allocative skill。skill 会准备构建产物、运行项目,并生成内存快照和计数报告。
默认基准项目
skill 默认使用仓库内置的基准项目,并按需准备项目文件。不指定项目或测试用例时,默认采集 Three.js 10 倍规模的开发构建:
也可以指定预设工作负载,例如使用 threejs-10x-production-sourcemap 采集启用 sourcemap 的生产构建。
外部项目
采集外部项目时,指定项目目录和构建模式:
--project-dir 是由 agent 解释的 skill 请求参数——不是 Rspack CLI 参数。相对路径基于 agent 的初始工作目录解析,包含空格的路径需要加引号。也可以用自然语言描述项目目录。项目目录决定工作负载,Rspack checkout 决定使用的本地 binding 和 JavaScript 包。如果项目有多个配置,请在请求中指定配置文件和构建模式。
Rspack 测试用例
skill 支持直接使用 Rspack 的测试用例采集数据,指定用例目录即可。例如:
例如,使用 hotCases/source-map/disable 用例,会得到以下内存快照文件:
每份快照还会生成对应的 .counts.json、.metadata.json 和 .warnings.txt 文件。
建议每次使用独立的输出目录,避免覆盖已有数据。skill 会报告选定的项目、构建方式、采集阶段、输出路径和覆盖限制。按照查看快照中的说明,在 Speedscope 中检查结果。
查看快照
快照从 compiler 和注册的全局根对象出发,沿所有权路径遍历。权重表示字节数,而非执行时间或内存分配事件。
打开 Speedscope,将 .allocative 文件拖入页面。使用搜索和缩放定位数据结构,选择 Left Heavy 查看最大的所有权路径。
较宽的节点表示更多字节。路径描述所有权关系,而非内存分配时的调用栈。folded 格式不包含单位,因此即使查看器显示了其他标签,也应将权重理解为字节。对于这些快照,Time Order 不表示时间线。
解读总量前,请阅读对应的 .metadata.json 和 .warnings.txt。metadata 包含所表示的字节总量、共享所有权计量策略,以及全局字符串 arena 的使用情况。warnings 会指出无法访问的嵌套分配和其他覆盖缺口。
读取条目计数
.counts.json 文件记录当前 compilation 模块图中的模块和依赖条目,并按类型分组。这些数值表示集合基数——而非整个进程的对象数或分配次数。空模块图会输出明确的模块和依赖零值。
不要用字节权重除以类型大小,也不要统计 .allocative 文件的行数来推算对象数量。集合容量可能超过长度,多个引用也可能共享同一块内存。
有计数数据时,skill 会自动生成 summary.json、counts.csv 和 counts.folded。可以在 Speedscope 中打开非空的 counts.folded,查看以条目数为权重的分布,而非字节。零值会保留在表格和汇总中,但不会生成图表节点。
解读结果
比较相同阶段、相同工作负载的快照。例如,反复进行 HMR 更新时,如果模块和依赖条目数保持稳定,而所表示的字节增加,可以进一步查看哪些所有权路径保留了更多数据。仅凭这种现象,还不能确定存在内存泄漏。
限制:
- 快照不测量 RSS、峰值内存或累计分配。
- JavaScript 和 V8 堆对象、回调捕获、部分外部状态、分配器元数据和容器的私有开销无法完整计入。非阻塞锁和不支持的嵌套类型也可能造成覆盖缺口。
进阶
内存采集的工作原理
Rspack 在 crates/rspack_allocative 中维护了 Buck2 的 allocative fork。这个 fork 通过 Rust 的编译期反射和编译器 driver,在大部分场景下自动收集内存数据,减少手动实现 Allocative 的需要。
借用引用不代表所有权,裸指针和不支持的值会作为不透明对象处理。共享分配只计入首次遇到的所有者路径。这些策略可以避免重复计入共享数据,但无法访问的状态仍会造成覆盖缺口。
需要手动实现 Allocative 的场景。 普通结构体和大多数枚举可以自动实现,但以下几种情况需要手动实现适配器或添加属性注解:
- 第三方类型需要在
rspack_allocative中补充对应的Allocative实现。 - Union 不被 derive 宏支持,只能手写
Allocative实现。 - 自定义所有权,即内存布局与实际所有权不一致的情况,比如 arena 分配的数据、借用缓冲区、共享指针等。需要手写实现来表达正确的遍历逻辑。
- 不透明或无法遍历的值,如裸指针、回调捕获、V8 堆对象。用
#[allocative(skip)]标记这些字段,将它们排除在外。 - 泛型约束不正确时,用
#[allocative(bound = "...")]自行指定约束。 - 枚举反射的边界场景。 编译器 driver 的枚举反射要求
Self: 'static,带生命周期参数、const 泛型或非字面量数组类型的枚举会跳过。这些枚举会回退到类型化遍历,需要显式的Allocative实现。
采集流程如下:
采集点位于 compiler/mod.rs 和 compiler/rebuild.rs。snapshot_allocative 负责遍历根对象并写出文件。这些数据表示采集时刻所覆盖的内存,具体限制见解读结果。
构建本地 binding
配置好开发环境后,在 Rspack 仓库根目录执行:
debug 构建默认包含 allocative 支持,快照采集仍默认关闭。 build:binding:debug 命令使用 release-debug Cargo profile。标准 release 构建不包含 allocative 支持。profiling 构建也默认包含该支持:
要在 development 构建(build:binding:dev)或其他 binding 构建配置中包含 allocative 支持,需要在构建时设置 ALLOCATIVE=1:
仅在运行时设置 ALLOCATIVE=1,无法为已有的 binding 增加采集能力。debug 和 profiling 构建也只有在设置 RSPACK_ALLOCATIVE_DIR 后,才会输出快照。
分析本地构建或测试
在目标项目的工作目录中运行构建后的 CLI:
使用本地 binding 的测试,也可以通过 RSPACK_ALLOCATIVE_DIR 采集快照。每次构建或重建都会自动输出快照,测试框架无需额外接入采集逻辑。构建好 binding 和 JavaScript 包后,可以运行单个 HMR 用例:
位置参数中保留的双引号用于精确选择 HotNode.test.mjs runner,-t 用于选择用例。请使用一个 worker 和新的输出目录。使用其他 runner 或多个并发进程时,应为每个进程分配独立目录,避免覆盖文件。仓库测试约定见测试指南。
生成计数报告
对于手动采集的快照,可以使用报告工具,并指定新的输出目录:
工具会发现匹配的附加文件,生成读取条目计数中介绍的汇总和计数报告。使用 skill 时,这一步会自动执行。

