查找一组字符串与一组字节串的内存大小

Find the memory size of a set of strings vs. set of bytestrings

编辑: 的答案也适用于集合。


通过分析我机器上的 RAM 使用情况(使用进程管理器),我注意到一组像 'abcd' 这样的数百万个字符串比一组数百万字节占用的内存少得多 b'abcd' (编辑:我错了,是别处出错了)。我想测试一下:

import random, string, sys
randomstring = lambda length: ''.join(random.choice(string.ascii_lowercase) for _ in range(length))
s1 = {randomstring(10) for i in range(100_000)}
s2 = {randomstring(50) for i in range(100_000)}
s3 = {randomstring(10).encode() for i in range(100_000)} 
s4 = {randomstring(50).encode() for i in range(100_000)} 
print(sys.getsizeof(s1), sys.getsizeof(s2), sys.getsizeof(s3), sys.getsizeof(s4))

但这里它总是给出相同的大小:4194528 而大小应该随因子 x5 而变化,并且对于字符串与字节的情况可能不同。

如何测量这些集合及其所有元素占用的内存大小?

注意:我知道在 Python 中找到结构占用的全部内存并不容易(另请参阅 In-memory size of a Python structure),因为我们需要考虑所有链接元素。

TL;DR: Python中有没有工具可以自动测量一个集合的内存大小+内部引用(指针?)占用的内存? ,哈希表桶,集合中托管的元素(此处为字符串)...?简而言之:这组字符串所需的每个字节。有这样的内存测量工具吗?

sys.getsizeof 不测量完整目标数据结构的大小。它仅测量包含 references 到 strings/bytes 对象的 set 对象占用的内存。 引用不包含在返回的内存消耗中(即它不递归遍历目标数据结构的每个对象)。在 64 位平台上,引用通常需要 8 个字节,并且 CPython 集不像列表那样紧凑:它的实现类似于 hash-table,有许多 和一些桶未使用。事实上,为了这个数据结构要快,这是强制性的(一般来说,occupancy应该是50%-90%)。此外,每个桶包含一个哈希,通常需要 8 个字节。

字符串本身比一个存储桶占用 space 多得多(至少在我的机器上):

sys.getsizeof(randomstring(50))           # 99
sys.getsizeof(randomstring(50).encode())  # 83

在我的机器上,事实证明 CPython 字符串比字节大 16 个字节。