Python的json模块内存使用量巨大?

10

当我将文件加载到json中时,Python的内存使用量会急剧增加到约1.8GB,并且似乎无法释放该内存。我编写了一个非常简单的测试用例:

with open("test_file.json", 'r') as f:
    j = json.load(f)

很抱歉我不能提供样例json文件,因为我的测试文件包含大量敏感信息,但是为了解释上下文,我正在处理一个大约240MB的文件。在运行以上两行代码后,我使用了先前提到的1.8GB内存。如果我接下来执行 del j ,内存使用量没有任何下降。然后我再加一句 gc.collect() ,内存仍然没有下降。我甚至试图卸载json模块并运行另一个gc.collect。

我正在尝试进行一些内存分析,但是heapy已经100%占用CPU约一个小时了,并且尚未产生任何输出。

有人有什么想法吗?我也尝试过使用cjson而不是打包的json模块。cjson使用的内存少约30%,但其他问题完全相同。

我在Ubuntu服务器11.10上运行Python 2.7.2。

我很乐意加载任何内存分析器,并查看它是否比heapy更好,并提供您认为必要的任何诊断。我正在寻找一个大型测试json文件,可以提供给其他人进行测试。


相关:https://dev59.com/2XE95IYBdhLWcg3wOLU1 - ChristopheD
@ChristopheD 我的问题在于内存从未被释放。我并不太关心在解析期间使用了大量内存。 - Endophage
1
@heltonbiker 我已经用几个不同的文件试过了,内存使用量似乎与 json 的大小直接相关,但不释放内存的问题是普遍存在的。 - Endophage
1
  1. 你确定已经不再强烈引用解析的JSON对象了吗?
  2. 内存是否会持续增加,例如如果导入两次,它是否会达到3GB?还是只会增加到“最大数据集”?(我不确定Python是否可以/会“释放内存给操作系统”,但许多运行时不能或不会这样做。也就是说,GC可以运行并回收Python引擎的内存,但它不一定会将其返回给操作系统,进程仍然会显示高值在top等中。)
- user166390
1
@Endophage:这可能只是意味着数组恰好是连续的页面(甚至是在内存顶部的连续页面),而JSON对象则分散在各个地方,通常与仍然活动的结果共享页面,因此无法返回到操作系统。 - abarnert
显示剩余4条评论
1个回答

15

我认为这两个链接涉及了一些有趣的观点,不一定是JSON问题,而是“大对象”问题以及Python与操作系统之间如何处理内存的差异。

请参见为什么在删除大对象时 Python 不会释放内存? ,了解为什么从Python中释放的内存不一定反映在操作系统上:

如果您创建一个大对象并将其删除,Python可能已经释放了内存,但涉及的内存分配器不一定将内存返回给操作系统,因此Python进程使用的虚拟内存看起来可能比实际使用的要多得多。

关于在子进程中运行大对象进程以让操作系统处理清理:

确保大量但临时的内存使用完成后将所有资源返还给系统唯一可靠的方法就是在子进程中进行此类内存占用的工作,然后终止该进程。在这种情况下,操作系统将履行其职责,并愉快地回收子进程可能吃掉的所有资源。好消息是, multiprocessing模块使得这种操作(过去比较麻烦)在Python的现代版本中变得不那么糟糕。


2
请确保包含相关的摘录/示例以抵消互联网上数据的不稳定性 :) - user166390
非常令人沮丧。你的第一个片段似乎准确描述了情况。 - Endophage
@Endophage:是的,我记得几个月前看到过一个类似的问题,关于大型JSON文件。 OP正在尝试使用4种不同的JSON库,以找到最节省内存的方法。 - jdi
我想我会选择多进程的方式。这样一来,当所有处理完成后,我就可以杀死该进程,而我的主进程则保持较小的内存占用。 - Endophage
1
@jdi 太棒了!你是最棒的!对于任何感兴趣的人,我收到了这个关于操作系统如何从PyCon 2012分配内存的精彩视频 http://pyvideo.org/video/717/python-linkers-and-virtual-memory - Endophage

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接