2

因此,我正在编写一个 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)
4

2 回答 2

5

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

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

于 2013-11-27T20:51:21.680 回答
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 中的引擎盖。

于 2013-12-13T15:00:58.870 回答