mmap 请求的内存大小对可用内存有什么影响?
What affect on available free memory does the size of memory requested by mmap have?
我了解 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 时,重新映射到 10MB 然后再映射回 1GB 以释放不再立即需要的 990MB 是否是一个可行的解决方案,但仍然提供对它的即时访问下次?我假设这会比 realloc 操作快得多?
我这里的一些假设可能不正确。我试图更好地了解 mmap 如何影响可用内存,以及 mremap 与使用 malloc 和 realloc 的性能影响。
以上内容基于现代 linux 内核,使用 gcc,假设 4k 页面大小和超出此范围的可移植性,不是重要的优先事项。
对于大多数处理器,当 运行 Linux 你是对的。 mmap
一千兆字节的 space 将只占用几 KB。它超过了您的 16kb,因为必须分配 "page tables" 来跟踪您分配的内存地址,但不会 多 。
现代 malloc
通常会几乎直接使用 mmap
进行大分配,所以如果你 malloc
一个巨大的 space 你会得到与使用几乎相同的效果mmap
直接...可能(但不保证)。
您可能应该做的一件事是将 MAP_NORESERVE
添加到您的标志(如果已定义)以确保 space 实际上没有分配到某处。在 Linux 上,此标志 通常 几乎没有(或没有)影响,但对于最近内核的特定配置 mmap
将 除非你给出这个标志,否则将在交换中分配。
但是请注意,某些 Unix(以及我认为 Linux 下的某些处理器类型)您将无法分配尽可能多的地址 space。如果 mmap
被拒绝,您应该准备好使用较小的映射重试。
最后一件事,如果您 mmap 巨大的 space 并且 Linux 后来发现它的订阅过多,它将终止进程。确保您有 过多的 交换量 space。您可以通过在 /tmp 上有一个 30GB 的 tmpfs 来证明它的合理性(具有 8GB 的 RAM)。
可能值得进行大量的前期分配,不是因为您的程序使用了物理内存,而是因为虚拟[=22] =]记忆。在 32 位系统上,如果您有碎片堆,很可能不会进行任何可能的 1G 分配。但是如果你先分配它,较小的片段更有可能正确地安排自己。
在64位系统上,运行 out of virtual address space 不是问题,但我怀疑分配它仍有优势前期。您可能会查看 madvise(MADV_HUGEPAGE)
以保存分页表 space。
此外,您可以 madvise(MADV_DONTNEED)
而不是 mremap
。
我了解 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 时,重新映射到 10MB 然后再映射回 1GB 以释放不再立即需要的 990MB 是否是一个可行的解决方案,但仍然提供对它的即时访问下次?我假设这会比 realloc 操作快得多?
我这里的一些假设可能不正确。我试图更好地了解 mmap 如何影响可用内存,以及 mremap 与使用 malloc 和 realloc 的性能影响。
以上内容基于现代 linux 内核,使用 gcc,假设 4k 页面大小和超出此范围的可移植性,不是重要的优先事项。
对于大多数处理器,当 运行 Linux 你是对的。 mmap
一千兆字节的 space 将只占用几 KB。它超过了您的 16kb,因为必须分配 "page tables" 来跟踪您分配的内存地址,但不会 多 。
现代 malloc
通常会几乎直接使用 mmap
进行大分配,所以如果你 malloc
一个巨大的 space 你会得到与使用几乎相同的效果mmap
直接...可能(但不保证)。
您可能应该做的一件事是将 MAP_NORESERVE
添加到您的标志(如果已定义)以确保 space 实际上没有分配到某处。在 Linux 上,此标志 通常 几乎没有(或没有)影响,但对于最近内核的特定配置 mmap
将 除非你给出这个标志,否则将在交换中分配。
但是请注意,某些 Unix(以及我认为 Linux 下的某些处理器类型)您将无法分配尽可能多的地址 space。如果 mmap
被拒绝,您应该准备好使用较小的映射重试。
最后一件事,如果您 mmap 巨大的 space 并且 Linux 后来发现它的订阅过多,它将终止进程。确保您有 过多的 交换量 space。您可以通过在 /tmp 上有一个 30GB 的 tmpfs 来证明它的合理性(具有 8GB 的 RAM)。
可能值得进行大量的前期分配,不是因为您的程序使用了物理内存,而是因为虚拟[=22] =]记忆。在 32 位系统上,如果您有碎片堆,很可能不会进行任何可能的 1G 分配。但是如果你先分配它,较小的片段更有可能正确地安排自己。
在64位系统上,运行 out of virtual address space 不是问题,但我怀疑分配它仍有优势前期。您可能会查看 madvise(MADV_HUGEPAGE)
以保存分页表 space。
此外,您可以 madvise(MADV_DONTNEED)
而不是 mremap
。