为什么py-leveldb的WriteBatch的使用会导致内存泄漏?

时间:2013-08-27 21:56:28

标签: python memory-leaks leveldb

所以我正在编写一个Python脚本,用于通过地址索引比特币区块链,使用leveldb数据库(py-leveldb),它会一直吃掉越来越多的内存,直到崩溃为止。我已经在下面的代码示例中复制了该行为。当我运行代码时,它继续使用越来越多的内存,直到它耗尽了我系统上的可用RAM并且进程被杀死或抛出“std :: bad_alloc”。

我做错了吗?我一直在写批处理对象,并且每隔一段时间提交一次,但即使我在WriteBatch对象中提交数据,内存使用量也在不断增加。我甚至在编写后删除了WriteBatch对象,所以据我所知它不会导致内存泄漏。

我的代码是否以错误的方式使用WriteBatch或py-leveldb中是否存在内存泄漏?

代码需要运行py-leveldb,从此处获取:https://pypi.python.org/pypi/leveldb

警告:如果运行时间过长,运行此代码将耗尽您的内存。不要在一个关键的系统上运行。此外,它会将数据写入脚本运行的同一文件夹中的文件夹,在我的系统上,此文件夹包含大约1.5GB的数据库文件,然后内存耗尽(最终消耗超过3GB的RAM)。

以下是代码:

import leveldb, random, string

RANDOM_DB_NAME = "db-DetmREnTrKjd"
KEYLEN = 10
VALLEN = 30
num_keys = 1000
iterations = 100000000
commit_every = 1000000

leveldb.DestroyDB(RANDOM_DB_NAME)
db = leveldb.LevelDB(RANDOM_DB_NAME)

batch = leveldb.WriteBatch()

#generate a random list of keys to be used
key_list = [''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(KEYLEN)) for i in range(0,num_keys)]

for k in xrange(iterations):
    #select a random key from the key list
    key_index = random.randrange(0,1000)
    key = key_list[key_index]

    try:
        prev_val = db.Get(key)
    except KeyError:
        prev_val = ""

    random_val = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(VALLEN))
    #write the current random value plus any value that might already be there
    batch.Put(key, prev_val + random_val)

    if k % commit_every == 0:
        print "Comitting batch %d/%d..." % (k/commit_every, iterations/commit_every)
        db.Write(batch, sync=True)
        del batch
        batch = leveldb.WriteBatch()

db.Write(batch, sync=True)

2 个答案:

答案 0 :(得分:5)

你应该真的尝试Plyvel。见https://plyvel.readthedocs.org/。它具有更清晰的代码,更多的功能,更快的速度和更多的测试。我用它来批量写入相当大的数据库(20+ GB)而没有任何问题。

(完全披露:我是作者。)

答案 1 :(得分:1)

我使用http://code.google.com/p/leveldb-py/

我没有足够的信息参与python leveldb驱动程序的烘烤,但我喜欢leveldb-py的简单性。它是使用ctypes的单个python文件。我用它来存储大约300万个密钥的文件,存储大约10GB,从未注意到内存问题。

对于你的实际问题: 您可以尝试使用批量大小。

你的代码,使用leveldb-py并为每个密钥执行put,在我的系统上使用少于20MB的内存工作正常。

我从这里(http://ayende.com/blog/161412/reviewing-leveldb-part-iii-writebatch-isnt-what-you-think-it-is)开始,在leveldb的引擎盖下有很多记忆副本。