41

我正在运行一些动态编程代码(试图强力反驳 Collat​​z 猜想 =P),并且我正在使用 dict 来存储我已经计算过的链的长度。显然,它在某个时候耗尽了内存。有没有什么简单的方法可以使用 a 的某些变体,dict当它用完空间时,它会将自身的一部分分页到磁盘?显然它会比内存中的字典慢,并且最终可能会占用我的硬盘空间,但这可能适用于其他不是那么无用的问题。

我意识到基于磁盘的字典几乎是一个数据库,所以我使用 sqlite3 手动实现了一个,但我没有以任何聪明的方式做到这一点,而是让它一次查找数据库中的每个元素......它慢了大约 300 倍。

创建我自己的一组字典,一次只在内存中保留一个,并以某种有效的方式将它们分页是最聪明的方法吗?

4

8 回答 8

58

The 3rd party shove module is also worth taking a look at. It's very similar to shelve in that it is a simple dict-like object, however it can store to various backends (such as file, SVN, and S3), provides optional compression, and is even threadsafe. It's a very handy module

from shove import Shove

mem_store = Shove()
file_store = Shove('file://mystore')

file_store['key'] = value
于 2008-10-23T07:22:01.207 回答
22

Hash-on-disk 通常使用 Berkeley DB 或类似的东西来解决 - Python Data Persistence 文档中列出了几个选项。你可以在它前面加上一个内存缓存,但我会先测试本机性能;有了操作系统缓存,它可能会出现相同的结果。

于 2008-10-22T17:34:09.927 回答
7

搁置模块可以做到;无论如何,它应该很容易测试。代替:

self.lengths = {}

做:

import shelve
self.lengths = shelve.open('lengths.shelf')

唯一的问题是货架的钥匙必须是字符串,所以你必须更换

self.lengths[indx]

self.lengths[str(indx)]

(我假设您的键只是整数,根据您对 Charles Duffy 帖子的评论)

内存中没有内置缓存,但您的操作系统可能会为您执行此操作。

[actually, that's not quite true: you can pass the argument 'writeback=True' on creation. The intent of this is to make sure storing lists and other mutable things in the shelf works correctly. But a side-effect is that the whole dictionary is cached in memory. Since this caused problems for you, it's probably not a good idea :-) ]

于 2008-10-23T02:21:40.547 回答
6

上次我遇到这样的问题时,我重写了使用 SQLite 而不是 dict,并且性能有了很大的提升。这种性能提升至少部分是由于数据库的索引能力。取决于您的算法,YMMV。

一个瘦包装器,可以在其中执行 SQLite 查询,__getitem__并且__setitem__不需要编写太多代码。

于 2008-10-22T17:37:24.880 回答
3

稍加思考,您似乎可以让搁置模块做您想做的事。

于 2008-10-22T18:01:42.630 回答
1

I've read you think shelve is too slow and you tried to hack your own dict using sqlite.

Another did this too :

http://sebsauvage.net/python/snyppets/index.html#dbdict

It seems pretty efficient (and sebsauvage is a pretty good coder). Maybe you could give it a try ?

于 2008-11-18T10:51:35.327 回答
0

如果有一些启发式方法可以知道接下来最有可能检索哪些项目,那么您一次应该携带多个项目,并且不要忘记查尔斯提到的索引。

于 2008-10-22T17:50:46.023 回答
0

For simple use cases sqlitedict can help. However when you have much more complex databases you might one to try one of the more upvoted answers.

于 2019-11-14T06:17:35.783 回答