2 回答
TA贡献1809条经验 获得超8个赞
首先,您绝对没有内存泄漏。如果它在接近500MB时就“崩溃”并且永不越过,则可能不会泄漏。
我的猜测是,您根本不会有任何问题。
当Python的垃圾回收器清理掉所有东西时(通常在CPython中使用完后立即发生),它实际上并没有真正释放内存到OS。相反,它可以解决问题,以备日后需要时使用。这是有意的—除非您不愿意进行交换,但是重用内存比保持释放和重新分配要快得多。
另外,如果500MB是虚拟内存,那么在现代64位平台上就没有任何内容了。如果它没有映射到物理/驻留内存(或者在计算机空闲时被映射,否则很快就被扔掉了),这不是问题。只是操作系统对有效免费的资源非常满意。
更重要的是:是什么让您认为有问题?是否有任何实际症状,或者在程序管理器/活动监视器/顶部/什么让您感到害怕?(如果是后者,请查看其他程序。在我的Mac上,我目前有28个程序正在使用超过400MB的虚拟内存运行,并且我正在使用16GB中的11个程序,即使少于3GB例如,如果我启动Logic,则将以比Logic可用的速度更快的速度收集内存;在那之前,操作系统为何要浪费精力去映射内存(尤其是当它无法确保某些进程无法进行映射时)去要求它以后不使用的内存)?
但如果是一个真正的问题,有两种方法可以解决这个问题。
第一个技巧是在子进程中执行所有内存密集型操作,您可以杀死该进程并重新启动以恢复临时内存(例如,使用multiprocessing.Process或concurrent.futures.ProcessPoolExecutor)。
这通常会使事情变慢而不是变快。而且,当临时存储器大部分是直接进入GUI的东西,因此必须驻留在主进程中时,显然这并不容易。
另一个选择是弄清楚内存的使用位置,而不是同时保留这么多对象。基本上,有两个部分:
首先,在每个事件处理程序结束之前释放所有可能的东西。这意味着调用close文件(将del对象或将对它们的所有引用都设置为)None,调用destroy不可见的GUI对象,并且最重要的是,不存储对不需要的对象的引用。(PhotoImage使用后,您实际上是否需要保持周围环境?如果这样做,有什么方法可以按需加载图像?)
接下来,请确保您没有参考周期。在CPython中,只要没有循环,就立即清除垃圾-但是,如果有的话,它们会一直存在直到循环检查器运行为止。您可以使用该gc模块进行调查。要做的一件非常快的事情就是经常尝试:
print(gc.get_count())
gc.collect()
print(gc.get_count())
如果看到巨大的水滴,则说明有周期。您将必须查看gc.getobjects()和的内部gc.garbage,或附加回调,或者只是对您的代码进行推理才能找到循环的确切位置。对于每个引用,如果您真的不需要双向引用,请摆脱一个引用。如果您这样做,请将其中之一更改为weakref。
添加回答
举报