Python中数百万字符串列表的内存使用情况



如Find the memory size of a set of string vs.set of bytestrings所示,很难精确测量包含字符串的集合或列表所使用的内存。但这里有一个很好的估计/上限:

import os, psutil
process = psutil.Process(os.getpid())
a = process.memory_info().rss
L = [b"a%09i" % i for i in range(10_000_000)]
b = process.memory_info().rss
print(L[:10])  # [b'a000000000', b'a000000001', b'a000000002', b'a000000003', b'a000000004', b'a000000005', b'a000000006', b'a000000007', b'a000000008', b'a000000009']
print(b-a)
# 568762368 bytes

即对于100MB的实际数据为569MB。

改进这一点的解决方案(例如使用其他数据结构(已经在一组短字节字符串的Memory efficient数据结构中找到,并且Python中的set of 10 char string在RAM中是预期的10倍,所以这里我的问题不是";如何改进";,但是:

在标准字节字符串列表的情况下,我们如何准确地解释这种大小

每个字节字符串有多少字节,每个(链接的?(列表项最终获得569 MB?

这将有助于理解CPython(平台:Windows 64位(中列表和字节字符串的内部结构。

摘要:

列表对象的
  • 89 MB
  • 480 MB用于字符串对象
  • =>总计569 MB

sys.getsizeof(L)将告诉您列表对象本身大约为89MB。这是几十个组织字节,每个字节串引用8个字节,以及高达12.5%的过度分配,以实现高效的插入。

sys.getsizeof(one_of_your_bytestrings)会告诉你它们各有43个字节。那就是:

  • 8字节用于参考计数器
  • 指向类型的指针为8个字节
  • 长度为8个字节(因为字节串不是固定大小(
  • 8字节散列
  • 实际字节串内容为10个字节
  • 1字节表示终止的0字节

在内存中每43个字节存储一次对象将跨越内存字边界,这会更慢。所以它们实际上通常每48字节存储一次。您可以使用id(one_of_your_bytestrings)来获取要检查的地址。

(这里和那里有一些差异,部分原因是发生了确切的内存分配,但569 MB大约是知道上述原因的预期值,它与您测量的值相匹配。(

最新更新