我正在Python中构建一个灵活,轻量级的内存数据库,并发现了我查找值和使用索引的方式的性能问题。为了改善这一点,我尝试了一些选项,尝试平衡速度和内存使用。我当前的实现使用dicts的dict来按记录(对象引用)和字段(也是对象引用)存储数据。例如,如果我有三个记录有三个字段,其中一些数据丢失(即NULL值)::
{<Record1>: {<Field1>: 4, <Field2>: 'value', <Field3>: <Other Record>},
{<Record2>: {<Field1>: 4, <Field2>: 'value'},
{<Record3>: {<Field1>: 5}}
我认为是一个numpy数组,但是我仍然需要两个字典来将对象实例映射到数组索引,所以我看不出它会表现得更好。
索引是使用一对二分列表实现的,基本上充当从值到记录实例的映射。例如,以及上述Field1>
的索引:
[[4, 4, 5], [<Record1>, <Record2>, <Record3>]]
我以前使用的是一个简单的二进制文件,但是这不允许范围查找(例如所有值> 5)(参见Python hash table for fuzzy matching)。
我的问题是这个。我担心我有几个对象引用,并且索引中有相同值的多个副本。所有这些重复引用实际上是否使用更多内存,或者在python中是否便宜?我的另一种方法是尝试将一个数字键与每个对象相关联,这可能会改善至少256个,但我不知道python如何处理引用以了解这是否真的会更好。
有没有人有更好的方法来管理这个?
重新实现C中的关键部分是我想作为最后手段保留的选项。
对于任何有兴趣的人,我的代码是here。
修改1:
简单的问题是,在内存使用方面,以下哪项更有效,其中a
是对象实例,i
是整数:
[a] * 1000
或
[i] * 1000, {a: i}
编辑2:
由于大量评论表明我使用的是现有系统,因此这是我的要求。如果任何人都可以建议一个满足所有这些要求的系统,那就太好了,但到目前为止我还没有找到任何可行的系统。否则,我原来的问题仍然与python中的引用的内存使用有关。:
答案 0 :(得分:1)
每个引用实际上都是一个指针,每个指针都需要少量内存。
您可以使用memory profiler逐行查看内存使用情况。通过这种方式,您可以看到在进行参考时会发生什么。
答案 1 :(得分:0)
Python没有为动态内存管理指定特定的实现,但是从语言的语义可以假设引用使用类似于C指针的内存。
答案 2 :(得分:0)
FWIW,我在100x100结构上运行了一些测试,测试了一个稀疏填充的字典结构,一个完全填充的字典结构,一个列表和一个numpy数组。后两者有一个字典映射对象引用索引。我通过索引定时获取结构中的每个项目(返回稀疏字典中缺失数据的标记),并报告总大小。我的结果有点令人惊讶:
Structure Time Size
============= ======== =====
full dict 0.0236s 6284
list 0.0426s 13028
sparse dict 0.1079s 1676
array 0.2262s 12608
所以最快和最小的第二个是完整的dict,因为不需要对它进行key in dict
检查,因此可以推测。