gpt4 book ai didi

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

转载 作者:IT王子 更新时间:2023-10-28 23:38:01 25 4
gpt4 key购买 nike

我正在从面向对象的数据库中读取一组对象(表,如 sqlite3 表或数据帧),其中大部分都足够小,Python 垃圾收集器可以毫无意外地处理。但是,当它们变得更大(小于 10 MB)时,GC 似乎无法跟上。

伪代码如下所示:

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(大大减慢循环速度,我仍然会遇到某种类型的内存错误),
  • 3(循环仍然很慢,但内存最终还是会爆炸)

欢迎提出建议!!!

特别是,如果你能给我一些工具来帮助我进行自省(introspection)。我在这里使用过 Windows 任务管理器,它似乎或多或少地随机出现内存泄漏。我尽可能地限制了交易规模,这似乎有点帮助。

最佳答案

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

首先,也是最重要的,在 CPython 中,垃圾收集大部分是基于引用计数的。 gc.collect() 不会为您做任何事情(燃烧时间除外),除非垃圾对象涉及引用循环(对象 A 可以通过以下方式从自身访问从 A 可传递地到达的指针链)。您在您展示的代码中没有创建引用循环,但数据库层可能会这样做。

那么,在你运行 gc.collect() 之后,内存使用量会下降吗?如果没有,运行它是没有意义的。

我预计数据库层很可能持有对对象的引用的时间超过了必要的时间,但深入研究这一点需要深入了解数据库层如何实现的确切细节。

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

>>> import sys
>>> bigobj = [1] * 1000000
>>> sys.getrefcount(bigobj)
2

正如文档所说,结果通常比您希望的大 1,因为 getrefcount() 的参数的引用计数临时增加 1 仅仅是因为它 em> 被(暂时)用作参数。

因此,如果您看到一个大于 2 的引用计数,del 将不会释放该对象。

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

顺便说一句,您需要更清楚地了解“似乎不起作用”和“最终会爆炸”的意思。猜不透。 究竟出了什么问题?例如,是否引发了 MemoryError?还有什么?回溯通常会产生大量有用的线索。

关于python - 使用 Python 从 OODB 中读取不同大小的对象来管理内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19829448/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com