【问题标题】:Python json memory bloatPython json内存膨胀
【发布时间】:2011-06-30 14:39:55
【问题描述】:
import json
import time
from itertools import count

def keygen(size):
    for i in count(1):
        s = str(i)
        yield '0' * (size - len(s)) + str(s)

def jsontest(num):
    keys = keygen(20)
    kvjson = json.dumps(dict((keys.next(), '0' * 200) for i in range(num)))
    kvpairs = json.loads(kvjson)
    del kvpairs # Not required. Just to check if it makes any difference                            
    print 'load completed'

jsontest(500000)

while 1:
    time.sleep(1)

Linux top 表示 python 进程在完成 'jsontest' 函数后拥有 ~450Mb 的 RAM。如果省略了对“json.loads”的调用,则不会出现此问题。此函数执行后的 gc.collect确实会释放内存

看起来内存没有保存在任何缓存或 python 的内部内存分配器中,因为对 gc.collect 的显式调用正在释放内存。

这是因为从未达到垃圾回收的阈值(700、10、10)吗?

我确实在 jsontest 之后放了一些代码来模拟阈值。但这没有帮助。

【问题讨论】:

    标签: python json garbage-collection


    【解决方案1】:

    把它放在程序的顶部

    import gc
    gc.set_debug(gc.DEBUG_STATS)
    

    只要有集合,您就会得到打印输出。您会看到,在您的示例代码中,jsontest 完成后没有集合,直到程​​序退出。

    你可以放

    print gc.get_count()
    

    查看当前计数。第一个数字是自上次第 0 代收集以来分配超过释放的数量;第二个(resp.third)是自第 1 代(resp.2)的最后一次收集以来第 0 代(resp.1)被收集的次数。如果你在jsontest 完成后立即打印这些,你会看到计数是(548, 6, 0) 或类似的东西(毫无疑问,这会根据 Python 版本而有所不同)。所以没有达到阈值,也没有进行收集。

    这是基于阈值的垃圾收集调度的典型行为。如果需要空闲内存及时归还给操作系统,那么就需要将基于阈值的调度与基于时间的调度结合起来(即自上次回收后经过一定时间后,再请求一次回收) ,即使尚未达到阈值)。

    【讨论】:

    • 即使我们多次调用 jsontest,内存仍然保持在 ~450MB。这是上次 jsontest 调用使用的内存吗?此代码是处理 json 消息的 webapp 的一部分。即使在运行 webapp 一小时后,内存似乎也没有被释放。除了 gc.collect 之外,还有其他解决方法吗?
    • 在每次调用jsontest 后尝试打印gc.get_count(),一切都应该清楚。另外,打电话gc.collect有什么问题?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多