Red Hat Training

A Red Hat training course is available for RHEL 8

第 32 章 配置操作系统以优化内存访问

这部分论述了如何配置操作系统以优化工作负载的内存访问,以及用于这样做的工具。

32.1. 用于监控和诊断系统内存问题的工具

Red Hat Enterprise Linux 8 中提供了以下工具来监控系统性能并诊断与系统内存相关的性能问题:

  • vmstat procps-ng 软件包提供的工具显示系统进程、内存、分页、块 I/O、陷阱、磁盘和 CPU 活动的报告。它提供自计算机上次打开或上次报告之后平均这些事件的即时报告。
  • valgrind 框架为用户空间二进制文件提供了工具。使用 yum install valgrind 命令安装这个工具。它包含很多工具,您可以使用它们来分析和分析程序性能,例如:

    • memcheck 选项是默认的 valgrind 工具。它检测并报告一些难以检测和诊断的内存错误,例如:

      • 不应发生的内存访问
      • 未定义或未初始化值使用
      • 释放堆内存不正确
      • 指针重叠
      • 内存泄漏

        注意

        memcheck 只能报告这些错误,它无法阻止它们发生。但是,memcheck 在出错前立即记录错误消息。

    • cachegrind 选项模拟应用程序与系统的缓存层次结构和分支预测器的交互。它在应用执行期间收集统计信息,并将摘要输出到控制台。
    • massif 选项测量指定应用使用的堆空间。它测量有用的空间和分配用于预订和调整的其他空间。

其它资源

  • vmstat(8)valgrind(1) man page
  • /usr/share/doc/valgrind-version/valgrind_manual.pdf file

32.2. 系统内存概述

Linux 内核旨在最大限度地提高系统内存资源(RAM)的利用率。由于这些设计特征,根据工作负载的内存要求,系统部分内存正在内核中使用,代表工作负载使用,而内存的一小部分是空闲的。此可用内存保留给特殊系统分配,用于其他低优先级或高优先级系统服务。

系统内存的其余部分专用于工作负载本身,并分为以下两个类别:

File memory

在此类别中添加的页面代表永久存储中文件的一部分。这些页面可以从页面缓存中映射或取消映射应用的地址空格。您可以使用应用程序使用 mmap 系统调用将文件映射到其地址空间中,或者通过缓冲的 I/O 读写系统调用处理文件。

缓冲的 I/O 系统调用以及直接映射页面的应用程序可以重新利用未映射的页面。因此,这些页面由内核存储在缓存中,特别是在系统没有运行任何内存密集型任务时,以避免在同一组页面上重新发出昂贵的 I/O 操作。

Anonymous memory
此类别中的页面由动态分配的进程使用,或者与永久存储中的文件无关。这组页面备份每个任务的内存中控制结构,如应用堆栈和堆区域。

图 32.1. 内存用量模式

RHEL 内存使用模式

32.3. 虚拟内存参数

虚拟内存参数在 /proc/sys/vm 目录中列出。

以下是可用的虚拟内存参数:

vm.dirty_ratio
是百分比值。当修改系统内存总量的百分比时,系统开始使用 pdflush 操作写入磁盘修改。默认值为 20 %。
vm.dirty_background_ratio
百分比值.修改系统内存总量的百分比时,系统开始在后台将修改写入磁盘。默认值为 10 %。
vm.overcommit_memory

定义确定大型内存请求是接受还是拒绝的条件。默认值是 0

默认情况下,内核通过估算可用内存量和失败的请求量来执行启发式内存过量使用处理。但是,由于内存是使用启发式而不是精确算法来分配的,因此此设置可能会造成内存过载。

设置 overcommit_memory 参数的值:

  • 当将此参数设置为 1 时,内核不会执行内存过量使用处理。这增加了内存过载的可能性,但提高了内存密集型任务的性能。
  • 当将此参数设置为 2 时,内核会拒绝等于或大于可用交换空间总和 overcommit_ratio 中指定的物理 RAM 百分比的内存请求。这降低了过量使用内存的风险,但建议仅用于交换区域大于物理内存的系统。
vm.overcommit_ratio
指定 overcommit_memory 设置为 2 时考虑的物理 RAM 百分比。默认值为 50
vm.max_map_count
定义进程可以使用的最大内存映射区域数。默认值为 65530。如果您的应用程序需要更多内存映射区域,请提高这个值。
vm.min_free_kbytes

设置保留可用页面池的大小。它还负责设置管理 Linux 内核页面重新声明算法行为的 min_pagelow_pagehigh_page 阈值。它还指定了在系统中保持可用最小 KB 的数量。这会为每个低内存区域计算一个特定值,每个区按照其大小分配一组保留的可用页面。

设置 vm.min_free_kbytes 参数的值:

  • 增加参数值可有效减少应用程序的工作集合的可用内存。因此,您可能只将它用于由内核驱动的工作负载,其中驱动程序缓冲区需要在原子环境中分配。
  • 如果内存在系统中面临大量争用,则减少参数值可能会导致内核无法服务系统请求。

    警告

    极端值可能会影响系统的性能。将 vm.min_free_kbytes 设置为非常低的值可防止系统有效地回收内存,这会导致系统崩溃并导致服务中断或其他内核服务失败。但是,设置 vm.min_free_kbytes 过高会显著增加系统重新声明活动,从而导致错误直接重新声明状态导致分配延迟。这可能会导致系统立即输入内存不足状态。

    vm.min_free_kbytes 参数还设置一个页重新声明水位线,名为 min_pages。在决定控制页面回收算法的其他两个内存水位线 low_pageshigh_pages 时,这个水位线被用作因素。

/proc/PID/oom_adj

如果系统内存不足,且 panic_on_oom 参数被设置为 0oom_killer 功能会终止进程,从具有最高 oom_score 的进程开始,直到系统恢复为止。

oom_adj 参数决定进程的 oom_score。这个参数是为每个进程标识符设置的。-17 的值会禁用该进程的 oom_killer。其他有效值范围从 -1615

注意

由调整后的进程创建的进程将继承该进程的 oom_score

vm.swappiness

交换性值(范围从 0100 )控制系统首选从匿名内存池或页面缓存内存池回收内存的程度。

设置 swappiness 参数的值:

  • 更高的值优先是文件映射驱动的工作负载,而交换出不太活跃访问的进程的 RAM 映射内存。这可用于文件服务器或流应用程序,这些应用程序依赖存储中的文件(来自存储中的文件)驻留在内存中,以减少服务请求的 I/O 延迟。
  • 低值优先使用匿名映射的工作负载,同时回收页面缓存(文件映射内存)。此设置对于不大量依赖于文件系统信息、大量使用动态分配和私有内存的应用程序(如数学和编号阻塞应用程序)以及很少的硬件虚拟化管理器(如 QEMU)非常有用。

    vm.swappiness 参数的默认值是 30

    警告

    vm.swappiness 设置为 0 会积极避免将匿名内存交换到磁盘中,这会增加内存或 I/O 密集型工作负载时被 oom_killer 功能终止的风险。

其它资源

32.4. 文件系统参数

文件系统参数在 /proc/sys/fs 目录中列出。以下是可用文件系统参数:

aio-max-nr
定义所有活跃的异步输入/输出上下文中允许的最大事件数。默认值为 65536,修改这个值不会预先分配或调整任何内核数据结构的大小。
file-max

确定整个系统处理的最大文件数。Red Hat Enterprise Linux 8 中的默认值是 8192,或者内核启动时可用的内存页面中有一个,以更长的时间为准。

增加这个值可解决缺少可用文件 handle 导致的错误。

其它资源

  • sysctl(8) man page

32.5. 内核参数

内核参数的默认值位于 /proc/sys/kernel/ 目录中。这些值会在启动时由内核计算,具体取决于可用的系统资源。

以下是用来为 msg*shm* System V IPC(sysvipc)系统调用设置限制的可用内核参数:

msgmax
定义消息队列中任何单个消息允许的最大允许大小,以字节为单位。这个值不能超过队列(msgmnb)的大小。使用 sysctl msgmax 命令确定您系统中的当前 msgmax 值。
msgmnb
定义单个消息队列的最大字节大小。使用 sysctl msgmnb 命令确定您系统中的当前 msgmnb 值。
msgmni
定义消息队列标识符的最大数量,以及队列的最大数量。使用 sysctl msgmni 命令确定您系统中的当前 msgmni 值。
shmall
定义一次系统上可以使用的共享内存页面总量。例如:AMD64 和 Intel 64 架构中的 4096 字节是 字节。使用 sysctl shmall 命令确定您系统中的当前 shmall 值。
shmmax
定义内核允许的单个共享内存段的最大字节大小。使用 sysctl shmmax 命令确定您系统中的当前 shmmax 值。
shmmni
定义系统范围的最大共享内存片段数。默认值为所有系统中的 4096

其它资源

  • sysvipc(7)sysctl(8) man page