当前位置: 首页 > 面试题库 >

Python:减少字典的内存使用量

马清野
2023-03-14
问题内容

我正在尝试将几个文件加载到内存中。这些文件具有以下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的内存!(整个python应用程序不会将其他任何数据加载到内存中)。

文件少于10个,大多数文件将保持稳定在50-80k行,除了一个文件目前有数百万行。

因此,我想请求一种技术/数据结构来减少内存消耗:

  • 对压缩技术有什么建议吗?
  • 如果我仍然使用dict,有什么方法可以减少内存?是否可以像Java for Python dict那样设置“负载因子”?
  • 如果您还有其他数据结构,则我也愿意以某种速度进行交易以减少内存。尽管如此,这是一个对时间敏感的应用程序,因此,一旦用户输入了查询,我认为花几秒钟的时间返回结果并不是很合理。关于这一点,我仍然对Google如何如此快速地完成Google Translate感到惊讶:他们必须使用大量技术+大量服务器功能吗?

非常感谢你。我期待您的建议。


问题答案:

我无法提供有助于改善内存占用量的完整策略,但我认为这可能有助于分析占用大量内存的确切原因。

如果您查看字典的 Python实现
(这是哈希表的相对简单的实现),以及内置字符串和整数数据类型的实现,例如此处(特别是object.h,intobject
.h,stringobject.h和dictobject.h以及../Objects中相应的* .c文件),您可以准确地计算出预期的空间需求:

  1. 一个 整数 是固定大小的对象,即,它包含一个引用计数,一个类型的指针和实际整数,在总通常 至少12个字节 在32位的系统上,并且 24个字节 在64位的系统上,没有考虑到额外的空间可能通过对齐而丢失。

  2. 字符串 对象是可变大小的,这意味着它包含

  3. 参考计数

  4. 类型指针

  5. 尺寸信息

  6. 延迟计算的哈希码的空间

  7. 状态信息(例如用于 插入 字符串)

  8. 指向动态内容的指针

总共32位 上至少24个字节 ,或64位上 至少 60个字节不包括字符串本身的空间。

  1. 词典 本身由多个动叶的,各自含有

  2. 当前存储的对象的哈希码(由于使用了冲突解决策略,因此无法从存储桶的位置进行预测)

  3. 指向关键对象的指针

  4. 指向值对象的指针

总共 32位 上至少12个 字节, 在64位上 至少 24个字节

  1. 字典从 8个空存储桶 开始,每当达到其容量时, 通过增加 条目数来 调整 字典的 大小

在32位计算机上使用46,461个唯一字符串(337,670字节串联的字符串大小)的列表 进行了测试 ,每个字符串都与一个整数相关联-
与您的设置类似。根据上述计算,我希望最小内存占用为

  • 46,461 *(24 + 12)字节= 1.6 MB(字符串/整数组合)
  • 337670 = 0.3 MB用于字符串内容
  • 65,536 * 12字节= 1.6 MB用于哈希存储桶(调整大小13次后)

总共2.65 MB。(对于64位系统,相应的计算结果为5.5 MB。)

空闲运行Python解释器时,根据ps-tool的占用空间为4.6 MB。因此,创建字典后,预期的总内存消耗约为4.6 + 2.65 = 7.25
MB。
我的测试中的 实际内存占用量(根据ps7.6 MB。
我想额外的约。Python的内存分配策略(用于内存竞技场等)产生的开销消耗了0.35 MB

当然,现在很多人会指出,我ps用来测量内存占用量是不准确的,并且我对32位和64位系统上的指针类型和整数大小的假设在许多特定系统上可能是错误的。授予。

但是,尽管如此,我相信 关键结论 是:

  • Python 字典实现 消耗的内存非常
  • 但是许多 int 和(特别是) 字符串对象 (用于引用计数,预先计算的哈希码等)所占用的空间比您最初想的要多
  • 几乎没有办法避免的内存开销 ,只要您使用Python,并希望表示为单个对象的字符串和整数-至少我看不出怎么能作到
  • 寻找(或自己实现) Python-C扩展 可能会值得,该 扩展 实现了将键和值存储为C指针(而不是Python对象)的哈希。我不知道那是否存在。但我相信这是可以做到的,并且可以将内存占用空间减少一半以上。


 类似资料:
  • 我正在使用spring boot开发客户端应用程序。在运行spring boot应用程序(使用完全可执行的jar)时,x64服务器的内存占用约为190M,x86服务器的内存占用约为110M。 我的jvm选项是(-xmx64m-xms64m-xx:maxpermsize=64m-server),为什么在x64服务器中,内存占用这么大?如何将内存使用量降低到150M以下? 多谢了。

  • 我有一个Java程序可以在Solaris 10 X86上运行,具有2GB物理内存和2GB交换。 该程序在64位Linux中运行良好,仅消耗约450MB内存。 然而,当它在Solaris中运行时,它总是报告OutOfMemoryError,我注意到在错误发生之前,它正试图使用 那么为什么JVM会尝试使用那么多虚拟内存呢?有没有办法告诉JVM不要使用那么多虚拟内存? 谢谢你。 编辑: 谢谢大家的意见!

  • 本文向大家介绍详解如何减少python内存的消耗,包括了详解如何减少python内存的消耗的使用技巧和注意事项,需要的朋友参考一下 Python 打算删除大量涉及像C和C++语言那样的复杂内存管理。当对象离开范围,就会被自动垃圾收集器回收。然而,对于由 Python 开发的大型且长期运行的系统来说,内存管理是不容小觑的事情。 在这篇博客中,我将会分享关于减少 Python 内存消耗的方法和分析导致

  • 问题内容: 我正在编写独立于操作系统的无锁队列,到目前为止,它工作得很好,但是内存管理方面的问题很小。我不确定它的gcc问题还是我的。问题:将元素添加到列表时,内存增加,但是从列表中删除元素(free(elementPointer);)时,内存使用率没有变化。 但是,当我使用pthreads时,N个生产者和M个消费者的 内存使用量始终约为10mb(当尝试添加和删除〜10kk元素时),因此看起来自由

  • 问题内容: 我想问你如何减少Spring框架的RAM占用量。 我创建了一个简单的helloworld应用来演示该问题。只有两个类和context.xml文件: -主要方法课 -用于模拟某些“工作”的类(无穷循环中的printig Hello) 仅包含以下内容: 测试类仅包含称为的方法,构造后会调用: 我准备了两种情况,在这两种情况下,方法仅包含一行。 在第一种情况下,主要方法是这样做的: App在

  • 问题内容: 背景 我有一个Spring批处理程序,该程序读取一个文件(我正在使用的示例文件的大小约为4 GB),对该文件进行少量处理,然后将其写到Oracle数据库中。 我的程序使用1个线程读取文件,并使用12个工作线程进行处理和数据库推送。 我正在搅动很多年轻一代的记忆,这使我的程序运行得比我想象的要慢。 建立 JDK 1.6.18 春季批处理2.1.x 4核计算机,带16 GB内存 问题 使用