首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Python从OODB中读取不同大小的对象来管理内存

用Python从OODB中读取不同大小的对象来管理内存
EN

Stack Overflow用户
提问于 2013-11-07 06:33:39
回答 1查看 279关注 0票数 7

我正在从面向对象的DataBase中读取对象的集合(如sqlite3表或dataframes),其中大多数都足够小,以至于Python垃圾收集器可以在不发生事故的情况下处理。但是,当它们变大(小于10 MB)时,GC似乎无法跟上。

psuedocode如下所示:

代码语言:javascript
复制
walk = walkgenerator('/path')
objs = objgenerator(walk)
with db.transaction(bundle=True, maxSize=10000, maxParts=10): 
    oldobj = None
    oldtable = None
    for obj in objs:
        currenttable = obj.table
        if oldtable and oldtable in currenttable:
            db.delete(oldobj.path)
        del oldtable
        oldtable = currenttable
        del oldobj
        oldobj = obj
        if not count % 100:
            gc.collect()

我正在寻找一种优雅的方法来管理内存,同时允许Python在可能的情况下处理它。

也许令人尴尬的是,我已经尝试使用del来帮助清理引用计数。

我在for循环中尝试了不同模数的gc.collect():

  • 100 (无差异),
  • 1(慢循环很多,我仍然会得到某种类型的内存错误),
  • (循环仍然很慢,但内存最终还是会崩溃)

非常感谢您的建议!!

特别是,如果你能给我一些工具来帮助我进行内省。我在这里使用过Windows任务管理器,它似乎或多或少地随机触发了内存泄漏。我已经限制了事务的大小,我觉得很舒服,这似乎有点帮助。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-11-22 20:02:35

这里没有足够的信息可以多说,但我要说的话不适合发表评论,所以我会在这里发布;-)

首先,也是最重要的是,在CPython中,垃圾收集主要基于引用计数。gc.collect()不会为您做任何事情(烧录时间除外),除非在引用周期中涉及垃圾对象(可以通过跟踪可从A传递到的指针链从自身到达对象A )。您在显示的代码中没有创建引用周期,但是数据库层可能会这样做。

那么,在您运行gc.collect()之后,内存使用会完全减少吗?如果不是,运行它是毫无意义的。

我预计数据库层保存对象引用的时间很可能超过了必要的时间,但深入了解这一点需要深入了解数据库层是如何实现的。

获取线索的一种方法是打印应用于各种大型对象的sys.getrefcount()的结果:

代码语言:javascript
复制
>>> import sys
>>> bigobj = [1] * 1000000
>>> sys.getrefcount(bigobj)
2

正如文档所述,结果通常比您可能希望的要大1,因为getrefcount()参数的拒绝数暂时增加1,只是因为它被用作参数(暂时)。

因此,如果你看到的折算大于2,del不会释放这个物体。

获取线索的另一种方法是将对象传递给gc.get_referrers()。它返回直接引用参数的对象列表(前提是引用者参与Python的循环gc)。

顺便说一句,你需要弄清楚你所说的“似乎不管用”和“最终爆炸”是什么意思。猜不出来。到底出了什么问题?例如,是MemoryError引发的吗?还有别的吗?折中往往产生了一个有用的线索世界。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19829448

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档