如何强制释放字典使用的内存?

bea*_*rdo 6 python memory dictionary memory-leaks memory-management

我正在开发一个 Python 脚本,该脚本查询多个不同的数据库以整理数据并将所述数据保存到另一个数据库。该脚本从大约 15 个不同数据库的数百万条记录中收集数据。为了尝试加速脚本,我包含了一些缓存功能,归结为拥有一个包含一些经常查询的数据的字典。字典保存键值对,其中键是根据数据库名称、集合名称和查询条件生成的哈希值,值是从数据库中检索到的数据。例如:

{123456789: {_id: '1', someField: 'someValue'}}哪里123456789是散列,{_id: '1', someField: 'someValue'}是从数据库中检索到的数据。

将这些数据保存在本地字典中意味着不必每次都查询数据库(这可能很慢),我可以在本地访问一些经常查询的数据。如前所述,有很多查询,因此字典可能会变得非常大(几 GB)。我有一些代码psutil用于查看运行脚本的机器上有多少内存可用,如果可用内存低于某个阈值,我会清除字典。清除字典的代码是:

cached_documents.clear()
cached_documents = None
gc.collect()
cached_documents = {}
Run Code Online (Sandbox Code Playgroud)

我应该指出这cached_documents是一个局部变量,它被传递到所有访问或添加到缓存的方法中。不幸的是,这似乎还不足以正确释放内存,因为即使在调用了上述代码之后,Python 仍然占用大量额外内存。您可以在此处查看内存使用情况:

在此处输入图片说明

值得注意的是,字典被清除的前几次,我们向系统释放了大量内存,但随后的每次似乎都更少,此时内存使用量趋于平缓,因为缓存被非常频繁地清除,因为自从可用内存在阈值内,因为 Python 占用了大量内存。

有没有办法在清除字典时强制 Python 正确释放内存,以避免平铺?任何提示表示赞赏。

bea*_*rdo 0

根据我原来帖子的评论,我做了一些修改。

正如评论中提到的,在进程结束之前,Python 似乎无法可靠地将内存返回给操作系统。在某些应用程序中,这意味着您可以启动一个单独的进程来完成内存密集型工作。有关更多详细信息,请参阅在 Python 中释放内存

不幸的是,这不适用于我的情况,因为重点是在需要时将数据存储在内存中。

由于 Python 保留了一些分配的内存并使其可用于其他 Python 对象,因此我更新了脚本的标准以清除缓存。我没有根据可用的系统内存来设置清除缓存的条件,而是根据缓存大小设置清除缓存的条件。基本原理是,我可以继续填充缓存并重用 Python 持有的内存。我通过对我的问题中的图表中缓存被清除的前几次进行粗略平均,找到了缓存大小阈值,然后稍微减少数量以增加一点余地(例如,大小为 10 的缓存可以使用不同的数量)基于缓存内内容的内存)。

这比根据可用内存清除缓存安全性较差,因为缓存有可能增长到大于系统上的可用内存,从而导致内存不足错误;特别是如果系统上运行的其他进程需要大量内存,但对于我的用例来说,这是一个合适的权衡。

现在,根据缓存的大小而不是可用的系统内存来清除缓存,我似乎能够利用 Python 保留内存。尽管这可能不是一个完美的答案,但就我而言,它似乎有效。