如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大约是知道上述原因的预期值,它与您测量的值相匹配。(