我使用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')
答案 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应用程序的其余部分。这对我来说都很好。