我正在使用python字符串观察一个奇怪的内存使用模式 FreeBSD版本。考虑 以下会议。想法是创建一个包含一些的列表 字符串,以便列表中的累积字符为100MB。
l = []
for i in xrange(100000):
l.append(str(i) * (1000/len(str(i))))
这会按预期使用大约100MB的内存,'del l'将清除它。
l = []
for i in xrange(20000):
l.append(str(i) * (5000/len(str(i))))
这是使用165MB的内存。我真的不明白在哪里 额外的内存使用来自。 [两个列表的大小相同]
FreeBSD 7.2上的Python 2.6.4。在Linux / Windows上都使用 仅100mb内存。
更新:我正在使用'ps aux'测量内存。在上面的代码片段之后,可以使用os.sytem执行该操作。这些也是分别执行的。
Update2:看起来像freebsd mallocs内存的2的倍数。所以分配5KB实际上分配8KB。我不确定。
答案 0 :(得分:1)
在我看来,这可能是记忆中的碎片。首先,大于255字节的内存块将在CPython中与malloc一起分配。你可以参考
Improving Python's Memory Allocator
出于性能原因,大多数内存分配(如malloc)将返回一个对齐的地址。例如,您永远不会得到像
这样的地址0x00003
它没有对齐4个字节,计算机访问内存的速度会非常慢。因此,malloc获得的所有地址都应该是
0x00000
0x00004
0x00008
等等。 4字节对齐只是基本的通用规则,对齐的真正策略是OS变体。
你所谈论的内存使用量应该是RSS(不确定)。对于大多数操作系统,虚拟内存的页面大小为4K。对于您分配的内容,您需要2页来存储5000字节的块。让我们看一个例子来说明一些内存泄漏。我们假设这里的对齐是256个字节。
0x00000 {
... chunk 1
0x01388 }
0x01389 {
... fragment 1
0x013FF }
0x01400 {
... chunk 2
0x02788 }
0x02789 {
... fragment 2
0x027FF }
0x02800 {
... chunk 3
0x03B88 }
0x03B89 {
... fragment 3
0x04000 }
正如您所看到的,内存中存在如此多的片段,它们无法使用,但仍占用页面的内存空间。我不确定FreeBSD的对齐策略是什么,但我认为这是由于这样的原因造成的。为了有效地使用Python,你可以使用一大块预先分配的bytearray,并选择一个好的数字作为要使用的块(你必须测试知道哪个数字是最好的,它取决于操作系统)
答案 1 :(得分:0)
答案可能在this saga。我认为你正在目睹一些不可避免的内存管理器开销。
正如@Hossein所说,尝试在一次运行中执行两个代码片段,然后交换它们。
答案 2 :(得分:0)
我认为freebsd中的所有内存地址都必须与2的幂对齐。因此,所有python的内存池都有点碎片到内存中而不是连续的。
尝试使用其他tool来发现任何有趣的内容