
“drop了实例,RSS怎么没回来?”这个问题里至少混着三件事:句柄是否消失、实例资源是否归还、操作系统是否回收物理页。我先查owner,不从一张RSS截图判断泄漏。
2026-10-20发布的Wasmtime 50.0.0说明新增了Engine::release_idle_pool_memory,用于释放池中空闲槽位保留的驻留内存。这正说明“槽位空闲”和“全部驻留页已归还”需要分别观察。本文没有调用或实测该API。

账本不是一条析构箭头
官方快速实例化文档解释了池分配器:实例资源归还后可以被池复用。该文档是滚动版本,示例不能不经核对便当成50.0.0已验证代码。
| 账目 | 主要核对对象 | 不应直接推导 |
|---|---|---|
| 编译代码、池配置 | Engine及其克隆 | 删除一个变量即全局销毁 |
| 实例相关运行状态 | Store的生命周期 | drop Instance句柄必定立即清空Store资源 |
| 空闲池槽位 | 池容量、驻留策略 | 空闲等于没有虚拟映射 |
| 宿主缓冲 | Store数据、闭包、外部Arc | Store退出等于外部Arc也消失 |
Instance是Store关联的运行时句柄,不能按“一个普通Box拥有全部实例字节”来理解。宿主另外保留的Arc,则可能继续持有一份与Wasm线性内存完全不同的缓冲;这不表示它让已销毁的Store复活。
用纯Rust演示宿主引用
use std::sync::Arc;
struct HostBuffer(Vec<u8>);
struct StoreLike { _host: Arc<HostBuffer> }
fn main() {
let engine_pool = Arc::new(vec![0u8; 32]);
let pool_weak = Arc::downgrade(&engine_pool);
let host = Arc::new(HostBuffer(vec![0u8; 16]));
let host_weak = Arc::downgrade(&host);
let store = StoreLike { _host: host.clone() };
assert_eq!(Arc::strong_count(&host),2);
drop(store);
assert_eq!(Arc::strong_count(&host),1);
assert_eq!(host.0.len(),16);
assert!(pool_weak.upgrade().is_some());
drop(host);
assert!(host_weak.upgrade().is_none());
drop(engine_pool);
assert!(pool_weak.upgrade().is_none());
println!("owner ledger passed; StoreLike is not Wasmtime");
}
保存为main.rs,rustc 1.98.0编译运行,引用计数与Weak观察断言通过。StoreLike只是教学结构;它证明外部Arc能延长宿主对象生命期,没有验证Wasmtime真实Store或池的实现。
怎样定位才不会误报
真实程序先固定运行时版本与分配策略,记录Engine、Store和宿主对象数量,再记录活跃与空闲池槽位。RSS、虚拟地址空间和映射文件各用对应指标,不能拿一种数代替全部。
若所有Store已销毁而RSS仍高,可能是池保留页、宿主引用、通用分配器缓存,或真正泄漏,需要逐层排除。只有保留对象的增长有证据,才给它贴泄漏标签。
本轮没有安装Wasmtime或运行内存曲线。已完成的是本地owner反例和发布说明核对。关于50.0.0新增方法的具体签名、调用限制与效果,集成时必须对固定版文档再验,不能照抄开发版接口。
本文探讨Wasmtime中Instance销毁后内存未释放的常见误解,区分句柄消失、资源归还和OS页回收三个层次;指出Arc引用计数、池分配器空闲槽位保留、宿主对象生命周期延长等关键因素;强调需结合Engine/Store数量、池状态及多维度内存指标(RSS、虚拟地址空间等)进行准确定位,避免误判内存泄漏。

1677

被折叠的 条评论
为什么被折叠?



