为什么Python以超过550k的密钥存储时会消耗更多的内存

时间:2015-06-08 10:43:47

标签: python

我使用Python的dict类型来存储一个包含超过550k密钥的数据文件,差不多是29M。但是,在读取数据文件后,使用的内存超过70M,这是不正常的。

那么,这是怎么发生的?

以下是读取数据文件的功能。

def _update_internal_metrics(self, signum, _):
    """Read the dumped metrics file"""
    logger.relayindex('reload dumped file begins')
    dumped_metrics_file_path = os.path.join(settings.DATA_DIR,
                                            settings.DUMPED_METRICS_FILE)
    epoch = int(time.time())
    try:
        new_metrics = {}
        with open(dumped_metrics_file_path) as dumped_metrics_file:
            for line in dumped_metrics_file:
                line = line.strip()
                new_metrics[line] = epoch
    except Exception:
        if not signum:
            self._reload_dumped_file()
        logger.relayindex("Dumped metrics file does not exist or can"
                          "not be read. No update")
    else:
        settings["metrics"] = new_metrics

    instrumentation.increment('dumped.Reload')
    logger.relayindex('reload dumped file ends')

1 个答案:

答案 0 :(得分:1)

首先,top不是检查它的正确方法,因为它会告诉你整个过程的内存消耗。您可以使用getsizeof模块中的sys

sys.getsizeof(new_metrics)

其次,字符串和哈希表都存在一些开销:

sys.getsizeof('')

在我的系统上,这是24字节开销,无论字符串大小如何,开销都是一致的。使用550k密钥,开销约为13M。

Python试图保持哈希表不会过于密集,因为这会导致查找时间过长。 AFAIK cpython实现使用2x增长因子,表大小为2 ^ k。由于您的密钥大小刚刚超过两倍(math.log(550000,2) # 19.06),因此2 ** 20 = 1048576个广告位相对稀疏。在64位系统上,每个字符串有8个字节的对象指针,这是额外的8M开销。您还存储整数,这些整数不在原始文件中(另一个8M),每个哈希表槽也包含存储的哈希值(另一个8M)。请参阅PyDictEntry的来源。

总共66M,当然你需要一些空间用于你的python应用程序的其余部分。这对我来说都很好。