基于Judy-array的解决方案似乎是我应该考虑的选择。我仍在寻找Python可以使用的良好实现。稍后将更新。
更新,
最后,我在http://pre.google.com/p/py-judy/上尝试了Judy数组包装器。那里似乎没有任何文档,但是我尝试仅通过dir(…)其包和对象来找到其方法,但是它可以工作。
同样的实验,使用judy.JudyIntObjectMap,它以标准dict的1/3占用了〜986MB的内存。它还提供JudyIntSet,在某些特殊情况下,与JudyIntObjectMap相比,它不需要引用任何实际的Python对象作为值,因此可以节省更多内存。
(如以下进一步测试所示,JudyArray仅使用几MB到几十MB,实际上〜986MB的大部分实际上是由Python内存空间中的值对象使用的。)
这是一些对您有帮助的代码,
>>> import judy>>> dir(judy)['JudyIntObjectMap', 'JudyIntSet', '__doc__', '__file__', '__name__', '__package__']>>> a=judy.JudyIntObjectMap()>>> dir(a)['__class__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__iter__', '__len__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__value_sizeof__', 'by_index', 'clear', 'get', 'iteritems', 'iterkeys', 'itervalues', 'pop']>>> a[100]=1>>> a[100]="str">>> a["str"]="str"Traceback (most recent call last): File "<stdin>", line 1, in <module>KeyError: 'non-integer keys not supported'>>> for i in xrange(30000000):... a[i]=i+30000000 #finally eats ~986MB memory...
更新,
好的,我们测试了一个30M int的JudyIntSet。
>>> a=judy.JudyIntSet()>>> a.add(1111111111111111111111111)Traceback (most recent call last): File "<stdin>", line 1, in <module>ValueError: we only support integers in the range [0, 2**64-1]
它总共仅使用5.7MB来存储30M顺序的int数组[0,30000000),这可能是由于JudyArray的自动压缩所致。709MB以上是bcz,我使用range(…)而不是更合适的xrange(…)来生成数据。
因此,具有30M int的JudyArray核心的大小完全可以忽略。
如果有人知道更完整的Judy Array包装器实现,请告诉我,因为此包装器仅包装JudyIntObjectMap和JudyIntSet。对于int-int
dict,JudyIntObjectMap仍然需要真正的python对象。如果我们只做counter_add并设置值,那么最好将int值存储在C空间中,而不要使用python对象。希望有人有兴趣创建或介绍一个:)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)