Python 中数百万字符串列表的内存使用情况
Memory usage of a list of millions of strings in Python
如 所示,很难精确测量包含字符串的集合或列表所使用的内存。但这是一个很好的 estimation/upper 界限:
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
即100 MB 实际数据需要 569 MB。
已在 and 中找到改进此问题的解决方案(例如使用其他数据结构),所以这里我的问题不是“如何改进”,而是:
在标准字节串列表的情况下,我们如何精确地解释这个大小?
每个字节串有多少字节,每个(链接?)列表项最终获得 569 MB?
这将有助于理解 CPython 中列表和字节串的内部结构(平台:Windows 64 位)。
总结:
- 列表对象 89 MB
- 480 MB 用于字符串对象
- => 总计 569 MB
sys.getsizeof(L)
会告诉您列表对象本身大约有 89 MB。这是几十个组织字节,每个字节串引用 8 个字节,以及高达 12.5% 的过度分配以允许高效插入。
sys.getsizeof(one_of_your_bytestrings)
会告诉你它们每个有 43 个字节。 That's:
- 8 个字节用于参考计数器
- 8 个字节用于指向类型的指针
- 长度为 8 个字节(因为字节串的大小不固定)
- 8 字节散列
- 10 个字节用于您的实际字节串内容
- 1 个字节用于终止 0 字节。
在内存中每 43 个字节存储对象会跨越内存字边界,这会更慢。所以它们实际上通常每 48 个字节存储一次。您可以使用 id(one_of_your_bytestrings)
获取要检查的地址。
(这里和那里存在一些差异,部分原因是发生了确切的内存分配,但 569 MB 是了解上述原因的预期值,它与您测量的值相符。)
如
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
即100 MB 实际数据需要 569 MB。
已在
在标准字节串列表的情况下,我们如何精确地解释这个大小?
每个字节串有多少字节,每个(链接?)列表项最终获得 569 MB?
这将有助于理解 CPython 中列表和字节串的内部结构(平台:Windows 64 位)。
总结:
- 列表对象 89 MB
- 480 MB 用于字符串对象
- => 总计 569 MB
sys.getsizeof(L)
会告诉您列表对象本身大约有 89 MB。这是几十个组织字节,每个字节串引用 8 个字节,以及高达 12.5% 的过度分配以允许高效插入。
sys.getsizeof(one_of_your_bytestrings)
会告诉你它们每个有 43 个字节。 That's:
- 8 个字节用于参考计数器
- 8 个字节用于指向类型的指针
- 长度为 8 个字节(因为字节串的大小不固定)
- 8 字节散列
- 10 个字节用于您的实际字节串内容
- 1 个字节用于终止 0 字节。
在内存中每 43 个字节存储对象会跨越内存字边界,这会更慢。所以它们实际上通常每 48 个字节存储一次。您可以使用 id(one_of_your_bytestrings)
获取要检查的地址。
(这里和那里存在一些差异,部分原因是发生了确切的内存分配,但 569 MB 是了解上述原因的预期值,它与您测量的值相符。)