- 主题:请教个内存占用的问题
我有段代码,逻辑总结起来比较简单:
@functools.cache
def a_long_time_calc(cis):
...
for n in (...):
cis = tuple(some_dic.keys())
# cis 有较不小概率是会重复的
calc_res = a_long_time_calc(cis)
another_long_time_proc(...)
...
因为for n 循环跑的次数比较多, 而且cis本身也不短,导致随程序运行,内存占用会越来越多,然后被系统杀死,用memory_profiler做prof看的结果就是cis = tuple(...)这里不停的占用内存,要命的地方是, some_dic是从数据库里根据n实时抓出来的,他的keys没有办法做成预定义的。在运行一段时间之后主动调用gc.collect也没有效果。
请教一下, 有没有办法在运行一段时间之后把cis这个内存释放掉啊。
--
FROM 221.224.37.*
我换了个2T内存的机器把程序完整跑了一遍prof, memory在cis = tuple(...)那边增加比较多,其他地方微乎其微。
【 在 kawolu 的大作中提到: 】
: 估计是有内存泄漏,只不过最后刚好在那里爆掉
:
--
FROM 221.224.37.*
生成器没法cache, a_long_time_calc非常耗时
【 在 annals 的大作中提到: 】
: 逻辑允许的话,用生成器呗
:
--
FROM 221.224.37.*
查过了, 就是a_long_time_calc会用, 我也试过不用functools.cache, 自己维护一个cache,因为cache有几乎一半的概率会被命中,按道理来说循环结束后会把多次命中的key释放掉,但也没有。
我现在再想对数据库的数据做个预处理行不行,比如再存个本地数据库比如ZODB之类,把cis存到数据库里,利用持久化共享的特性来减少重复cis的内存占用。
【 在 RunningOn 的大作中提到: 】
: 我遇到过这样的问题,后面都解决了,方法无外乎两种:
: 1. cis没有被释放,是因为cis里有的对象被使用并保存了,导致cis不会被释放,比如其它
: 地方有类似于`a_global_list.append(cis[0])`这样的代码。这个得你自己查。
: ...................
--
FROM 221.224.37.*
没用,引用的对象在gc前会被放到一个临时区里面,即使没有字面的变量绑定到他。
【 在 dgiij 的大作中提到: 】
: @functools.cache
: def a_long_time_calc(cis):
: ...
: ...................
--
FROM 221.224.37.*
谢谢诸位,问题解决了。
还是对原数据库的数据做了预处理,使用ZODB又另外实时建了一个临时数据库,把那个一堆的数据存成OOBTree而不是dict。
原理是, OOBTree的keys是可hash的,但每次取keys的地址不一样,所以弄了个带cache的实现,这个cache又可以存到数据库里。
内存降到之前1/3左右。代价就是速度慢了些,会写个比较大的临时文件出来。
【 在 pcal 的大作中提到: 】
: 我有段代码,逻辑总结起来比较简单:
: @functools.cache
: def a_long_time_calc(cis):
: ...................
--
FROM 221.224.37.*