【问题标题】:What affect on available free memory does the size of memory requested by mmap have?mmap 请求的内存大小对可用内存有什么影响?
【发布时间】:2015-05-07 02:04:06
【问题描述】:

我了解 mmap 请求的内存在被读取或写入之前不会被实际使用。所以在下面的测试用例中:

int main()
  {
  char *A=mmap(NULL,1073741824/4, PROT_WRITE|PROT_READ,MAP_PRIVATE|MAP_ANONYMOUS,-1,0); 
  *A='a';
  char *B=mmap(NULL,1073741824/4, PROT_WRITE|PROT_READ,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
  *B='b';
  char *C=mmap(NULL,1073741824/4, PROT_WRITE|PROT_READ,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
  *C='c';
  char *D=mmap(NULL,1073741824/4, PROT_WRITE|PROT_READ,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
  *D='d'
  char *E=mmap(NULL,1073741824/4, PROT_WRITE|PROT_READ,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
  }

我是否正确假设其他程序可用的内存仅减少了 16k (4 x 4096)?我没有看到使用free() 会进一步减少可用内存,所以我假设是这样。

在这种情况下,假设我的应用程序通常使用 10MB 内存,但在极少数情况下可能突然需要高达 1GB(尽可能少的延迟)。一开始就映射 1GB 内存是一个可行的解决方案吗?据推测,虽然只使用了 10MB,但剩余的 990MB 可用于其他应用程序。当需要 1GB 的罕见情况发生时,我认为延迟会比 malloc 或 realloc 少得多。

当不再需要额外的 990MB 时,将 mremap 到 10MB 然后回到 1GB 以释放不再立即需要的 990MB 是否是一个可行的解决方案,但仍然可以为下次提供即时访问?我认为这会比重新分配操作快得多?

我在这里的一些假设可能是不正确的。我试图更好地了解 mmap 如何影响空闲内存,以及 mremap 与使用 malloc 和 realloc 的性能影响。

以上内容基于现代 linux 内核,使用 gcc,假设 4k 页面大小和超出此范围的可移植性,不是重要的优先事项。

【问题讨论】:

  • 当您不再需要内存时,请考虑使用madvise(...., MADV_DONTNEED) 而不是取消映射/重新映射。如果您不再需要内容,但希望保留它以供以后使用,这也可以用于(部分)大型 malloc 块。

标签: c linux memory memory-management


【解决方案1】:

对于大多数运行 Linux 的处理器来说,您是正确的。一千兆字节空间的mmap 只占用几KB。它超过了您的 16kb,因为必须分配“页表”以跟踪您分配的内存地址,但不会更多

现代的malloc 通常将mmap 几乎直接用于大型分配,因此如果您malloc 一个巨大的空间,您将获得与直接使用mmap 几乎相同的效果......可能(但不能保证)。

您可能应该做的一件事是将MAP_NORESERVE 添加到您的标志(如果已定义)以确保空间实际上并未分配到某处。在 Linux 上,此标志通常几乎没有(或没有)影响,但对于最近内核的特定配置,mmap 在交换中分配,除非您提供此标志。

但请注意,某些 Unix(以及我认为 Linux 下的某些处理器类型)您将无法分配尽可能多的地址空间。如果mmap 被拒绝,您应该准备好使用较小的映射重试。

最后一件事,如果您对巨大的空间进行映射,而 Linux 后来发现它的订阅量太大,它将杀死进程。确保您有过多的交换空间。您可以通过在 /tmp 上拥有一个 30GB 的 tmpfs(具有 8GB 的​​ RAM)来证明这一点。

【讨论】:

  • s/下限/上限/g
  • 总会有限制,但可能会更低;我会改写:-)
【解决方案2】:

可能值得进行大量的前期分配,不是因为您的程序使用了什么物理内存,而是因为虚拟内存。在 32 位系统上,如果您有一个碎片堆,很可能不会进行任何可能的 1G 分配。但是,如果您先分配它,较小的片段更有可能正确排列。

在 64 位系统上,运行 虚拟地址空间不是问题,但我怀疑预先分配它仍有优势。您可以查看madvise(MADV_HUGEPAGE) 以节省分页空间。

另外,您可以用madvise(MADV_DONTNEED) 代替mremap

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-24
    • 2021-02-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多