了解 TCMalloc 的 "Bytes released to OS (aka unmapped)" 统计

Understanding TCMalloc's "Bytes released to OS (aka unmapped)" stat

我有一个进程在启动时消耗大量内存,但在引导进程后释放了大部分内存。我在之后打印的 TCMalloc 统计信息中看到以下内容:

#012MALLOC:       16635888 (   15.9 MiB) Bytes in use by application
#012MALLOC: +            0 (    0.0 MiB) Bytes in page heap freelist
#012MALLOC: +     20007352 (   19.1 MiB) Bytes in central cache freelist
#012MALLOC: +     26367680 (   25.1 MiB) Bytes in transfer cache freelist
#012MALLOC: +      7030680 (    6.7 MiB) Bytes in thread cache freelists
#012MALLOC: +      1978560 (    1.9 MiB) Bytes in malloc metadata
#012MALLOC: =     72020160 (   68.7 MiB) Actual memory used (physical + swap)
#012MALLOC: +    239607808 (  228.5 MiB) Bytes released to OS (aka unmapped). ***
#012MALLOC: =    311627968 (  297.2 MiB) Virtual address space used

这里我们看到有 ~228 MB“释放到 OS”,但它也表明这仍然是进程虚拟地址 space 的一部分。看到此日志记录后,使用 ps aux 看到的 VSZ 统计数据仍然很高这一事实证实了这一点。

当我 运行 使用 strace 执行同一个程序时,我可以看到:对 brk 的所有调用都在增加,并且对 munmap 的调用(根据大小)加起来不数量 mmap-ed(如上所示)。更糟糕的是,VSZ 随着时间的推移缓慢增加,因为我的进程在后台工作,日志记录显示 (***) 在记录这些统计信息时相应增加。

所以我的问题是:这个值代表什么?我的记忆有没有被释放?我能做些什么来防止这种消费增长?

这个值代表什么?

它表示 TCMalloc 已经告诉系统它不需要并且系统可以用于其他目的的内存量。

我的内存有没有被释放?

没有。 OS 已经决定,让它免费只是为了在程序需要它时再次使用它是一种浪费,并且决定在一个步骤中直接将它从一种用途切换到另一种用途,而不是经历了使其免费的两倍努力,只是不得不让它变得不免费。

我能做些什么来防止这种消费增长?

你为什么想要?如果程序以后需要内存,它只会使它更容易,最大限度地减少对系统空闲列表的争用,并且根本没有有害影响。 TCMalloc 已经告诉 OS(通过 madvise(DONTNEED))OS 可能会恢复内存,而 OS 已经决定释放它不是一个好主意必须在需要时再次使用它。您有充分的理由认为 OS 是错误的吗?

只需一步直接将内存从一个人转移到另一个人,比通过两个步骤释放它只是为了再次使用它要容易得多。空闲列表在负载下可能会发生争用,不使用它要简单得多。

您可以通过运行一些消耗大量内存然后终止的程序强制OS释放它。这将强制 OS 将内存转移到该进程,然后在该进程终止时释放它。但这根本不会带来任何好处,而且会付出很多努力,最终只会增加内存管理器中的争用。这里没有问题。