【问题标题】:Does virtual memory mapping fragmentation cause performance issue?虚拟内存映射碎片是否会导致性能问题?
【发布时间】:2019-06-17 23:05:49
【问题描述】:

我有一个应用程序,我首先使用 linux mmap 系统调用创建大型匿名映射(大约 4MB)。

然后在进程执行过程中,为了尽快释放内存,我在考虑取消映射较小的内存块,以便最初是大块的虚拟内存映射会导致碎片化。

这可能会由于虚拟内存转换表碎片而导致性能问题,还是内核使用智能策略来避免这种情况?我可以不介意虚拟内存映射的碎片吗?

【问题讨论】:

    标签: c linux memory-management linux-kernel virtual-memory


    【解决方案1】:

    简答:除非你随机分配大量最小粒度(即 4096 字节)的非连续区域,否则不会。


    长答案:有点,

    在现代架构中,您有多个级别的虚拟内存映射(或页表,无论您喜欢哪个术语),对于 64 位架构,通常为 48 位地址空间提供 4 级内存映射(英特尔即将推出的扩展将添加另一个级别,允许将 4096 字节页面分段为 256 字节页面)。每次你在一个尚不存在映射的区域中分配一个页面时,内核必须分配一个新的(通常物理上连续的;注意重点,相对而言这是一个相当昂贵的操作)块内存来保存该内存空间的该区域的翻译映射。我将避免使用特定于 Arch 的术语,而是将它们称为 L0 -> L1 -> L2 -> L3,而 L0 是代表该虚拟内存空间的根映射。这将随页面大小粒度和不同的操作系统或架构(例如 Linux 具有超级页面)而变化。

    现在,如果您的新映射位于 L3 级别,并且具有 L3 页表,则新映射将只涉及更改该区域中的条目以指示转换。如果没有L3页表,则必须分配一个新的L3页表,并进入L2页表。以此类推,一直到 L0 页表。

    几个快速说明:

    • 每次更改映射时,通常都会有一个 TLB(Translation Lookaside Buffer;MMU 用于 VM->Phys 转换的硬件缓存)失效惩罚(无论是手动还是自动)。
    • 某些页面可能不需要全部 4 个转换阶段,转换级别具有特定大小,因此超级页面通常是例如使用 L2 页表条目将该 VM 空间的整个块映射到物理空间的页面(这意味着只需要 3 级翻译)。
    • 各种架构使用不同的方法来减少 TLB 丢弃的损失(即 x86_64 上的 PCID;事实上,一些崩溃缓解措施(如 KPTI)在没有它的情况下会导致性能下降)。
    • 说到崩溃,某些内存范围可能具有内核或蹦床映射或异常向量。这些由操作系统保留。在 Spectre/Meltdown 之前的 64 位系统上,内核通常会将自己映射到每个页表中。许多 ARM 处理器都有一个专门的机制,称为拆分页表(TTBR0/TTBR1;转换表基址寄存器 0/1)。
    • 上面的一个例子是Linux VDSO(虚拟动态共享对象),它是由内核创建的映射。与之对应的 Darwin (OSX/iOS) 是 commpage(公共页面)。这通常具有系统中每个进程共享的只读代码,并且具有当前时间(为了降低系统调用的成本,gettimeofday 可以从 VDSO 中读取它或使用 VDSO 蹦床来读取它)。李>
    • 当然,以上所有内容都取决于您使用的体系结构和操作系统以及您使用的操作系统版本,因为虚拟内存管理器经常使用各种技术来确保不会出现碎片。 如果您随机请求大量小的固定映射,是的,您实际上会绕过很多映射,从而导致性能问题。

    【讨论】:

    • 我正在努力理解。假设我制作了一个 mmap,它完全适合 L3 页表(例如,虚拟内存页 1 到 10 与物理内存 A 到 J 相关联)。然后,如果我取消映射虚拟内存页 2、5、8,例如,内核将不会创建 L2 页表,因为 2、5、8 在先前分配的 L3 页表内。正确的? (1)
    • 尽管如此,与 2, 5, 8 (B,E,H) 关联的物理内存可能会被其他进程重用,不是吗? (2)
    • 内核不在页面错误时分配物理内存吗?页面错误的粒度是多少?它是一个完整的内存映射(例如,如果我首先访问 1 中的一个字节,内核故障 1-10 并保留 A 到 J),还是只保留一页物理内存? (3)
    • 也谢谢你的详细解释 Kristina :)。
    • 上次我检查(Linux 2.6)时,没有映射新的二进制文件,所以是的,最初每次从新页面读取都会导致页面错误,但是这取决于磁盘/块缓存层。现在使用 ASLR 很难说,因为在不影响安全性的情况下很难共享页表,并且要求这些页面上的代码完全是 PIC(仅与 PC 相关,也就是不需要重定位。这就是 VDSO 的工作方式)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-03
    • 2016-03-24
    • 2011-07-11
    • 2020-05-16
    相关资源
    最近更新 更多