< 返回版块

reison1218 发表于 2020-03-25 04:34

Tags:内存管理

最近做测试,用hashmap装结构体,循环往里面塞,然后用top -pid(mac电脑)查看进程信息,内存占用慢慢变高,但当循环remove时,内存一直没有减少,哪怕全部remove完了,过了一段时间,内存占用还是没有减少,那rust什么时候将虚拟内存还给系统呢?

评论区

写评论
zhuxiujia 2020-03-28 14:16

不管是rust也好,go,java,hashmap 都是有 cap 和len的。 意思是 它这个数据结构是 存在扩容和缩容的操作的, 我举个java的例子,java的hashmap是容量满75%时扩容。 所以说,你remove 掉(对象是回收了的,但是hashmap不一定)并不一定马上回收,除非容量缩小到满足rust的hashmap的 缩容策略时释放

phper-chen 2020-03-27 12:01

有的动态数据结构的堆内存回收并非立刻的 有的是 惰性回收

作者 reison1218 2020-03-25 17:25

刚又测试了一遍,只是换了点东西,把box里面的内容改小了,发现内存没有还给os,内存占用只有几百k,应该是内存分配器和os的优化吧,小内存没有必要频繁回收,因为之后很有可能还会用到,这样可以提高性能,只有大块内存,才会回收,感谢你提供的帮助,老哥! 对以下内容的回复:

作者 reison1218 2020-03-25 17:06

我之前是用的shrink_to_fit,行不通t^t 对以下内容的回复:

作者 reison1218 2020-03-25 17:04

考虑到分配器和os之间的关系,我之前也是这么想的 对以下内容的回复:

作者 reison1218 2020-03-25 17:02

感谢老哥,刚跑了一下你的测试代码,内存回收了,我写的测试跟你差不多,只不过没有你insert这么大进去,放结构体,放string都试过,然后我没用box,因为box分配在堆内存然后又实现了drop会自动释放?但也只是空出空余内存吧(虚拟内存),为什么打印进程信息内存回收了?因为大块内存会回收?为了让内存还给os,很多地方都用box(堆中分配)那不是很慢吗? 对以下内容的回复:

liyiheng 2020-03-25 13:01
use std::collections::HashMap;
use std::time::Duration;

fn main() {
    let pid = std::process::id();
    println!("My pid is {}", pid);
    let mut a = HashMap::new();
    for i in 0..1024u64 {
        a.insert(i, Box::new([0u8; 1024 * 1024]));
    }
    std::thread::sleep(Duration::from_secs(20));
    for i in 0..1024u64 {
        a.remove(&i);
    }
    for _ in 0..20 {
        std::thread::sleep(Duration::from_secs(1));
    }
}

这样似乎能看到内存被释放

gmg137 2020-03-25 09:53

rust 其实已经把内存释放了,但操作系统出于优化考虑并没有马上进行回收。以上纯属猜测。

songzhi 2020-03-25 09:04

应该是你的hashmap实例还在,它不会自动缩减释放之前分配的内存,可以尝试析构这个实例,或者调用shrink_to

1 共 9 条评论, 1 页