我正在尝试将几个文件加载到内存中。这些文件具有以下 3 种格式之一:
- 字符串 TAB 整型
- 字符串 TAB 浮点数
- int TAB 浮点数。
事实上,它们是 ngram 静态文件,以防这有助于解决问题。例如:
i_love TAB 10
love_you TAB 12
目前,我现在正在做的伪代码是
loadData(file):
data = {}
for line in file:
first, second = line.split('\t')
data[first] = int(second) #or float(second)
return data
令我惊讶的是,虽然磁盘中文件的总大小约为 21 mb,但加载到内存中时,该进程需要 120 - 180 mb 的内存! (整个Python应用程序不会将任何其他数据加载到内存中)。
文件数量不到10个,大部分都会稳定在50-80k行左右,除了一个文件目前有数百万行。
所以我想请求一种技术/数据结构来减少内存消耗:
- 对于压缩技术有什么建议吗?
- 如果我仍然使用dict,有什么办法可以减少内存吗?是否可以像 Java 中那样为 Python 字典设置“负载因子”?
- 如果您有其他一些数据结构,我也愿意牺牲一些速度来减少内存。然而,这是一个时间敏感的应用程序,因此一旦用户输入查询,我认为花费超过几秒钟的时间来返回结果是不太合理的。对此,我仍然对谷歌能够如此快地完成谷歌翻译感到惊讶:他们一定使用了很多技术+大量服务器的能力?
非常感谢。我期待您的建议。
我无法提供有助于改善内存占用的完整策略,但我相信这可能有助于分析到底是什么占用了这么多内存。
如果你看一下Python实现字典(这是哈希表的相对直接的实现),以及内置字符串和整数数据类型的实现,例如here https://svn.python.org/projects/python/trunk/Include/(特别是 object.h、intobject.h、stringobject.h 和 dictobject.h,以及 ../Objects 中相应的 *.c 文件),您可以以一定的精度计算预期的空间需求:
-
An integer是一个固定大小的对象,即它包含引用计数、类型指针和实际整数,通常总计至少 12 个字节在 32 位系统上和24 bytes在 64 位系统上,不考虑可能因对齐而丢失的额外空间。
-
A string对象是可变大小的,这意味着它包含
- The 字典本身由多个桶组成,每个桶包含
- 字典开头是8个空桶 and is 通过加倍调整大小达到其容量时的条目数。
我进行了测试包含 46,461 个唯一字符串(连接字符串大小为 337,670 字节)的列表,每个字符串都与一个整数关联 — 类似于您在 32 位计算机上的设置。根据上面的计算,我预计最小内存占用为
- 字符串/整数组合 46,461 * (24+12) 字节 = 1.6 MB
- 337,670 = 0.3 MB 字符串内容
- 哈希桶 65,536 * 12 字节 = 1.6 MB(调整大小 13 次后)
总共 2.65 MB。 (对于 64 位系统,相应的计算结果为 5.5 MB。)
当Python解释器空闲运行时,其占用空间根据ps
-工具为 4.6 MB。因此创建字典后预计总内存消耗约为 4.6 + 2.65 =7.25 MB. The 真实的内存占用(根据ps
)在我的测试中是7.6 MB.我猜额外的约。 Python 的内存分配策略(对于内存区域等)产生的开销消耗了 0.35 MB
当然现在很多人会指出我使用ps
测量内存占用量是不准确的,并且我对 32 位和 64 位系统上指针类型和整数大小的假设在许多特定系统上可能是错误的。的确。
但是,尽管如此,主要结论我相信,是这些:
- 蟒蛇字典实现消耗惊人small内存量
- 但很多人占用的空间int和(特别是)字符串对象,对于引用计数、预先计算的哈希码等,比您一开始想象的要多
- 有几乎没有办法避免内存开销,只要你使用 Python 并希望将字符串和整数表示为单独的对象 - 至少我不知道如何做到这一点
- 寻找(或自己实现)可能是值得的Python-C 扩展它实现了一个将键和值存储为 C 指针(而不是 Python 对象)的哈希。我不知道这是否存在;但我相信这是可以做到的,并且可以将内存占用减少一半以上。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)