【问题标题】:Python large variable RAM usagePython 大变量 RAM 使用情况
【发布时间】:2014-09-11 16:34:45
【问题描述】:

假设有一个 dict 变量在运行时变得非常大 - 多达数百万个键:值对。

此变量是否存储在 RAM 中,从而有效地耗尽了所有可用内存并减慢了系统的其余部分?

要求解释器显示整个字典是个坏主意,但只要一次访问一个键就可以了吗?

【问题讨论】:

  • 如果您认为需要巨大的内存,最好考虑迭代器和生成器

标签: python memory variables ram


【解决方案1】:

是的,字典将存储在进程内存中。因此,如果它变得足够大以至于系统 RAM 中没有足够的空间,那么随着系统开始在磁盘之间交换内存,您可能会看到速度大幅下降。

其他人说几百万件不应该造成问题;我不确定。 dict 开销本身(在计算键和值占用的内存之前)很重要。对于 Python 2.6 或更高版本,sys.getsizeof 提供了一些关于各种 Python 结构占用多少 RAM 的有用信息。一些快速的结果,来自 64 位 OS X 机器上的 Python 2.6:

>>> from sys import getsizeof
>>> getsizeof(dict((n, 0) for n in range(5462)))/5462.
144.03368729403149
>>> getsizeof(dict((n, 0) for n in range(5461)))/5461.
36.053470060428495

因此,在这台机器上,字典开销在每项 36 字节和每项 144 字节之间变化(确切值取决于字典的内部哈希表的完整程度;这里 5461 = 2**14//3 是其中之一内部哈希表被放大的阈值)。那是在为 dict 项目本身添加开销之前;如果它们都是短字符串(例如 6 个字符或更少),那么每个项目仍然会增加 >= 80 个字节(如果许多不同的键共享相同的值,则可能会更少)。

因此,在一台典型的机器上耗尽内存不会需要 几百万个 dict 项。

【讨论】:

  • 谢谢,从这里了解了getsizeof。实际上,我最多只会处理约 15k 的值,而且速度至关重要。我使用字典只是因为我根本没有接触过数据库,但我假设从硬盘读取和写入的数据库会比读/写字典慢?
  • 好的,对于这么大的字典,你应该没有任何问题。键和值的类型是什么?字符串?
  • 大部分是浮点数,一些字符串,一些列表
【解决方案2】:

数以百万计的项目的主要关注点不是字典本身,而是每个项目占用多少空间。不过,除非你做一些奇怪的事情,否则它们应该很合适。

但是,如果您有一个包含数百万个键的 dict,那么您可能做错了什么。您应该执行以下一项或两项:

  1. 弄清楚你应该实际使用什么数据结构,因为单个 dict 可能不是正确的答案。这究竟是什么取决于你在做什么。

  2. 使用数据库。你的 Python 应该带有一个 sqlite3 模块,所以这是一个开始。

【讨论】:

    【解决方案3】:

    是的,Python dict 存储在 RAM 中。然而,几百万个密钥对于现代计算机来说不是问题。如果您需要越来越多的数据并且 RAM 已用完,请考虑使用真实数据库。选项包括像 SQLite 这样的关系数据库(顺便说一下,内置在 Python 中)或像 Redis 这样的键值存储。

    在解释器中显示数百万个项目没有什么意义,但访问单个元素应该仍然非常有效。

    【讨论】:

      【解决方案4】:

      据我所知,Python 使用最好的散列算法,因此您可能会获得最佳的内存效率和性能。现在,整个内容是保存在 RAM 中还是提交到交换文件取决于您的操作系统,并且取决于您拥有的 RAM 量。 如果只是尝试一下,我想说的是最好的:

      from random import randint
      a = {}
      for i in xrange(10*10**6):
          a[i] = i
      

      当您运行它时,它的外观如何?在我的系统上占用大约 350Mb,至少可以说是可以管理的。

      【讨论】:

      • 我现在坚持使用的 comp 有 512 mb 的内存,这就是我担心的原因。但是我拥有的最多钥匙大约是 10k,所以我认为这应该不是问题。感谢您的测试,虽然我不会在这个上尝试。
      • 大多数操作系统在管理内存和交换方面都非常聪明。只要你有交换文件的硬盘空间,你真的应该用任何大小的字典。
      • 我猜这个 sn-p 中缺少一个随机因素 - 可能是字典键?
      • 每个键都相当于存储的值 - 但它仍然有效
      • @Kylotan, @PPTim:合法言论。 dict((i, -i) for i in xrange(107)) 大约为 440Mb。如果您使值不仅唯一而且浮动,您将获得高达 480Mb:dict((i, float(i) / 107) for i in xrange(10**7))。两者都不是虚拟内存无法处理的。
      猜你喜欢
      • 1970-01-01
      • 2013-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多