我想了几个文件加载到内存中。 该文件有下列任一3种格式:
- 串TAB INT
- 串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! (整个蟒应用程序不任何其他数据加载到存储器)。
还有不到10个文件,其中大部分将保持稳定在大约50-80k线,除了目前拥有数百万行的一个文件。
所以,我想问一个技术/数据结构来减少内存消耗:
- 有什么建议给压缩技术?
- 如果我还在用快译通,是有什么办法可以减少内存? 是否有可能在Java中设定的“负荷率”作为Python的字典?
- 如果你有一些其他的数据结构,“M也愿意牺牲一些速度,以减少内存。 然而,这是一个时间敏感的应用程序,这样,一旦用户输入他们的疑问,我觉得这是不太合理的花费超过几秒钟的时间返回结果。 关于这一点,我仍然由谷歌如何能做到谷歌翻译这么快惊讶:他们必须使用大量的技术+大量的服务器的权力吗?
非常感谢你。 我期待着您的咨询。
我不能提供一个完整的战略,这将有助于改善内存占用,但我相信它可以帮助分析究竟是采取这么多的内存。
如果你看一下Python实现词典的(这是一个相对直观的实现一个哈希表),以及内置的字符串和整数数据类型的实现,例如这里 (特别object.h,intobject .H,stringobject.h和dictobject.h,以及在../Objects相应的* .c文件),你可以用一些准确的预期空间要求计算:
的整数 。一个固定大小的对象,即,它包含一个引用计数,一个类型的指针和实际整数,在总通常为32位系统上的至少12个字节和一个64位的系统上的24个字节 ,不考虑额外的空间可能通过比对丢失。
一个字符串对象是可变大小的,这意味着它包含
- 引用计数
- 类型的指针
- 大小信息
- 对于懒惰地计算的散列代码空间
- 状态的信息(例如用于实习字符串)
- 的指针动态内容
在32位上总共至少24个字节或64位上60个字节 ,而不是包括用于字符串本身空间。
字典本身由多个动叶的,各自含有
- 当前存储的对象的哈希码(即不是从铲斗的位置可预测由于所使用的冲突解决策略)
- 一个指针到密钥对象
- 的指针值对象
在32位上总共至少12个字节和在64位24个字节 。
字典开始时用8个空水桶 , 通过在达到它的容量增加一倍时条目的数量调整大小 。
我进行的测试用的46461个唯一的字符串(337670个字节级联串大小),每个具有一个整数相关联的列表-相似于您的设置,在32位机器上。 根据上述计算,我期望的最低内存占用
- 46461 *(24 + 12)字节= 1.6 MB的字符串/整数的组合
- 337670 = 0.3 MB为字符串内容
- 65536个* 12个字节= 1.6 MB用于散列桶(调整大小的13倍)之后
总共2.65 MB。 (对于64位系统中的对应的计算产生5.5 MB)。
当运行Python解释器空闲,根据它的足迹ps
-工具是4.6 MB。 因此创建的字典后的总预期存储器消耗大约4.6 + 2.65 = 7.25 MB。 真正的内存占用(根据ps
)在我的测试是7.6 MB。 我想额外的约 0.35 MB是由通过Python的内存分配策略开销生成消耗(用于存储器领域等)
当然现在很多人会指出,我使用ps
来衡量内存占用是不准确的,我对指针类型和整数的32位和64位系统的大小假设可能是错误的许多具体制度。 理所当然的。
但是,尽管如此, 关键的结论 ,我相信,有这些:
- Python的字典执行占用内存的一个令人惊讶的少量
- 但受诸多int和(尤其是) 字符串对象采取的引用计数,预先计算的散列码等的空间,是比你想象的更先
- 几乎没有办法避免的内存开销 ,只要您使用Python,并希望表示为单个对象的字符串和整数-至少我看不出怎么能作到
- 这可能是值得寻找(或实现自己)一个Python-C的扩展 ,实现了存储键和值作为C-指针(而不是Python对象)的哈希。 我不知道是否存在; 但我相信这是可以做到,可能超过一半的减少内存占用。
1)SQLite的内存听起来像一个伟大的解决方案,它会让一旦加载这是一种享受,你更轻松地查询数据
sqlite3.connect( ':存储器:')
2)你可能想要一个名为元组 - 我敢肯定,他们比字典更轻,您可以访问使用的点符号(我有一个审美偏好反正)性能。
http://docs.python.org/dev/library/collections
3)你可能想看看的Redis: https://github.com/andymccurdy/redis-py
它是快速,将让你轻松坚持的事情,这意味着你不必加载整个集你想用的时候。
4)线索听起来是个好主意,但增加了一些理论的复杂性对你的工作结束。 您可以使用Redis的实现和存储它,虽然,这将进一步提高你的速度。
但总体而言,命名为元组可能是这里的伎俩。
在磁盘你刚才字符串,加载到Python解释器时,必须创建一个整体结构,每串并为每个字典,除了字符串本身。
有没有办法来减少由http://stardict.sourceforge.net/Dictionaries.php下载使用的内存,但也有其他的方式来解决这个问题。 如果你愿意牺牲一些速度,内存,你应该考虑存储和从SQLite的文件,而不是在内存中加载一切字典查询字符串。
听起来像特里( http://en.m.wikipedia.org/wiki/Trie )数据结构可能更适合您的内存效率的愿望。
更新:蟒蛇字典的存储效率已经提升为一个问题,但它是从给定的第三方库的可用性标准库拒绝。 请参阅: http://bugs.python.org/issue9520
你可以将其替换字典blist.sorteddict对于没有内存开销的log(n)的访问。 这是方便,因为它的行为完全像一本字典,即它实现了所有的方法,所以你只需要改变最初的类型。
如果你想在Python压缩存储在内存中的数值数据,你最好的解决方案可能是NumPy的。
numpy的( http://numpy.org )分配使用本机C的结构的数据结构。 它的大部分数据结构假设你存储一个数据类型,所以这不是适用于所有情况(您可能需要存储空,等等),但它可以是非常,非常,非常快,大约是一样紧凑你可以问。 科学的很多被用它做(参见:SciPy的)。
当然,还有另一种选择:zlib的 ,如果您有:
- 充足的CPU周期,和
- ,将不适合到内存中的大量数据
你可以只申报一个“页面”的数据(但大你想要的)作为数组,在数据读取方面,将其存储在阵列中,压缩它,然后在更多的数据读取,直到你有内存中的所有数据,你想。
然后,遍历网页,解压缩,转换回一个数组,并根据需要做您的操作。 例如:
def arrayToBlob(self, inArray):
a = array.array('f', inArray)
return a.tostring()
def blobToArray(self, blob, suppressWarning=False):
try:
out = array.array('f', [])
out.fromstring(blob)
except Exception, e:
if not suppressWarning:
msg = "Exception: blob2array, err: %s, in: %s" % (e, blob)
self.log.warning(msg)
raise Exception, msg
return out
一旦你有数据作为一个blob,你可以通过这个斑点为zlib和压缩数据。 如果你有大量重复值,这个斑点可以大大压缩。
当然,它比保持它的所有未压缩的速度较慢,但如果你不能在内存中适合它你的选择是有限的开始。
即使压缩,它可能无法全部装入内存,在这一点上,你可以写出来,压缩网页字符串或泡菜等
祝好运!