Memory management C/Pascal的堆管理器,自动用零字节填充释放的内存

Memory management C/Pascal的堆管理器,自动用零字节填充释放的内存,memory-management,heap,shared-memory,free,heap-memory,Memory Management,Heap,Shared Memory,Free,Heap Memory,您如何看待用零字节填充已释放(未实际使用)页面的选项?这可能会提高Windows、VMWare和其他虚拟机环境下的性能?例如,VMWare和HyperV计算内存页的哈希值,如果内容相同,则在同一主机上的虚拟机内部和虚拟机之间将此页标记为“共享”,直到修改该页为止。它有效地减少了内存消耗。Windows也这样做——它以不同的方式处理零页,将它们视为免费页面 我们可以使用堆管理器,当我们调用FreeMem/ReallocMem时,它会自动用零填充内存。作为另一种选择,我们可以有一个按需将空内存归零的

您如何看待用零字节填充已释放(未实际使用)页面的选项?这可能会提高Windows、VMWare和其他虚拟机环境下的性能?例如,VMWare和HyperV计算内存页的哈希值,如果内容相同,则在同一主机上的虚拟机内部和虚拟机之间将此页标记为“共享”,直到修改该页为止。它有效地减少了内存消耗。Windows也这样做——它以不同的方式处理零页,将它们视为免费页面

我们可以使用堆管理器,当我们调用FreeMem/ReallocMem时,它会自动用零填充内存。作为另一种选择,我们可以有一个按需将空内存归零的函数,即仅当显式调用此函数时。当然,这个函数必须是线程安全的。 用零填充内存的缺点是接触内存,内存可能已经变成虚拟内存,因此会出现页面错误。除此之外,任何内存存储操作都很慢,因此我们的程序会比较慢,尽管程度未知(可能可以忽略不计)

如果我们设法用零完全填充4K页面,系统管理程序或Windows将显式地将其标记为零页面。但即使部分归零也可能是有益的,因为虚拟机监控程序可能会使用LZ或类似算法压缩页面以节省物理内存

我只是想知道您的看法,堆管理器本身用零字节填充空堆内存的好处是否会超过这种技术的缺点


当我们购买减少的物理内存消耗时,归零是否值得它的价格?

如果堆在用户空间中,这将永远不会起作用。内核只能信任自己,而不能信任用户空间。如果内核将页面归零,则可以将其视为零。如果用户空间说它将一个页面归零,内核仍然需要检查这一点。它还不如把它归零。用户空间可以做的一件事就是丢弃页面。这标志着他们“不在乎”。然后内核可以将它们视为零。但手动将用户空间中的页面归零是徒劳的

当您有一个页面的内容您不再关心,但您仍希望将其分配时,您可以调用
VirtualAlloc
(和变体),并传递
MEM\u RESET
标志

发件人:

记忆重置

指示lpAddress和指定的内存范围中的数据 dwSize已不再受关注。这些页面不应从或从中读取 写入分页文件。但是,将使用内存块 后来又是这样,所以不应该取消它。此值不能为空 与任何其他值一起使用

使用此值并不保证 使用MEM_RESET操作的量程将包含零。如果你愿意 要包含零的范围,请取消对内存的调用,然后重新提交它

这两个方面都是最好的——您不需要将内存归零,系统也不需要将其重新分页。您可以利用经过良好调优的内存管理器,它已经有一个零池

Linux上的
MADV_FREE
(或
MADV_DONTNEED
用于Posix)标志下也存在类似的功能,以
madvise


我想知道是否有任何“安全”语言或操作系统会这样做,以最大限度地降低系统被攻击的风险,从而能够找到关键(但不再使用)数据。@manassehkatz-感谢您的观察。安全语言的内存归零造成的延迟是合理的。我的问题指向了另一个方向:零页重复数据消除导致的内存使用效率。当我们购买减少的物理内存消耗时,归零是否值得它的价格?谢谢您的解释!我认为你的解释只适用于在物理硬件上运行的Windows。但如果Windows在VMWare ESXi或HyperV下运行,您的解释不适用,不是吗?请参阅:也许我们应该检查一个CPUID位:如果我们在虚拟机监控程序下运行-清除内存,否则不清除。在裸机上运行时甚至不是这样。米奇:我想我们在这个概念上基本一致。我认为你的答案是更好地提供实际的文件和建议做什么!
/* 
 * Stack:
 * int shrink_heap (heap_info *h, long diff)
 * int heap_trim (heap_info *heap, size_t pad) at arena.c:660
 * void _int_free (mstate av, mchunkptr p, int have_lock) at malloc.c:4097
 * void __libc_free (void *mem) at malloc.c:2948
 * void free(void *mem)
 */

static int
shrink_heap (heap_info *h, long diff)
{
  long new_size;

  new_size = (long) h->size - diff;
  /* ... snip ...  */

  __madvise ((char *) h + new_size, diff, MADV_DONTNEED);

  /* ... snip ...  */
  h->size = new_size;
  return 0;
}