Linux 常见性能指标 -- 内存

发布时间:2024年01月19日

本系列记录操作系统常见性能指标,写这个主要是记录也是回顾,笔记很长,拆分了几个部分,本篇记录 内存?的性能指标

内存概念

这里需要解释一些内存相关的概念,帮助理解哪些是需要关注的指标,指标有什么影响;由于水平有限,如发现有问题欢迎指正,谢谢!

内存映射

Linux 内核给每个进程都提供了一个独立的虚拟地址空间,并且这个地址空间是连续的。

页表的映射下,进程就可以通过虚拟地址来访问物理内存。

页表实际上存储在 CPU 的内存管理单元 MMU 中,处理器就可以直接通过硬件,找出要访问的内存。

虚拟内存分布空间

内核空间:高地址

栈:包括局部变量和函数调用的上下文等。栈的大小是固定的,一般是 8 MB

文件映射:包括动态库、共享内存等,从高地址开始向下增长

堆:包括动态分配的内存,从低地址开始向上增长

数据段:包括全局变量等

只读段:包括代码和常量等

文件页?File Pages

文件页是映射到文件系统中的文件或通过内存映射的文件内容。它们通常用于缓存磁盘上的数据,以提高访问效率。

文件页是当文件被读取到内存中时创建的,它们可以被系统回收而不丢失数据,因为原始数据仍然保存在磁盘上。

描述:文件页可以释放回收,脏页写会磁盘再回收

常见文件页:缓存和缓冲区,通过内存映射获取的文件映射页

脏页:被应用程序修改过,并且暂时还没写入磁盘的数据

脏页回收的方式:

  • 在应用程序中,通过系统调用 fsync ,把脏页同步到磁盘中
  • 系统,由内核线程 kdmflush?(pdflush) 负责这些脏页的刷新

cat /proc/meminfo 的?Buffers 和?Cached

读写block 的时候,Buffers会增加

读写filesystem的时候,Cached 会增加

注意:从Linux内核3.10版本开始,pdflush的功能被合并到了kworker内核线程中。所以目前应该是 kdmflush 负责刷新

匿名页?Anonymous Pages

匿名页通常与用户空间的程序相关,如程序的堆和栈。它们不直接映射到磁盘上的任何文件。

匿名页是程序动态分配的内存,如果这些内存没有被交换(swap)到磁盘,那么当程序需要更多内存时,它们必须被释放。

描述:匿名页不可直接回收,可以被swap换出到磁盘后释放

常见匿名页:应用程序动态分配的堆内存

cat /proc/meminfo中的AnonPages字段可以显示当前系统中的匿名页数量

回收匿名页

系统可以通过Swap机制将这些不常访问的匿名页交换到磁盘上,从而释放内存。可以通过调整/proc/sys/vm/swappiness的值来控制这一行为,值越大就越使用swap (0-100,默认60)

# 查看内存使用情况
cat /proc/meminfo

# 调整内存回收阈值
sysctl -w vm.min_free_kbytes=10240

# 调整Swappiness值
sysctl -w vm.swappiness=60

内存分配与回收

内存分配

malloc() 是 C 标准库提供的内存分配函数,对应到系统调用上,有两种实现方式,即brk()和mmap()

对小块内存(小于 128K),C 标准库使用 brk() 来分配:

  • 通过移动堆顶的位置来分配内存
  • 内存释放后,会被缓存,可以重复使用
  • 在内存工作繁忙时,频繁的内存分配和释放会造成内存碎片

大块内存(大于 128K),则直接使用内存映射 mmap() 来分配:

  • 在文件映射段找一块空闲内存分配出去
  • 内存释放后直接回归系统
  • 在内存工作繁忙时,频繁的内存分配会导致大量的缺页异常,使内核的管理负担增大

这些内存,都只在首次访问时才分配,也就是通过缺页异常进入内核中,再由内核来分配内存

内存释放

主动释放

对内存来说,如果只分配而不释放,就会造成内存泄漏,甚至会耗尽系统内存。

所以,在应用程序用完内存后,还需要调用 free() 或 unmap() ,来释放这些不用的内存。

系统回收

1)回收缓存,比如使用 LRU(Least Recently Used)算法,回收最近使用最少的内存页面

2)回收不常访问的内存,把不常用的内存通过交换分区直接写到磁盘中

3)杀死进程,内存紧张时系统还会通过 OOM(Out of Memory),直接杀掉占用大量内存的进程

  • 一个进程消耗的内存越大,oom_score 就越大
  • 一个进程运行占用的 CPU 越多,oom_score 就越小

管理员可以通过 /proc 文件系统,手动设置进程的 oom_adj ,从而调整进程的 oom_score

oom_adj 的范围是 [-17, 15],数值越大,表示进程越容易被 OOM 杀死;

数值越小,表示进程越不容易被 OOM 杀死,其中 -17 表示禁止 OOM

例如: $(pidof sshd) 是指去查一下sshd 的 pid
echo -16 > /proc/$(pidof sshd)/oom_adj
内存回收策略
  1. 文件页很少时,会回收匿名页,回收匿名页会产生swap
  2. 如果没有swap,则只会回收文件页
  3. 如果有足够多的文件页,并且还有swap,依据swappiness 来确定回收比例
    1. swappiness=0 尽可能的回收文件页
    2. swappiness>0 值越大越倾向于回收匿名页,并产生swap

kswapd0 内核线程用来定期回收内存

  • pages_min:剩余内存小于页最小阈值,说明进程可用内存都耗尽了,只有内核才可以分配内存
  • pages_low:低于页低阈值时 kswapd0 会执行内存回收,直到剩余内存大于高阈值为止
  • pages_high:页高阈值与页低阈值间,说明内存有一定压力,但还可以满足新内存请求
  • 高于pages_high 表示没有内存压力
/proc/sys/vm/min_free_kbytes 设置页最小阈值,其他阈值由最小值计算得来

pages_low = pages_min*5/4
pages_high = pages_min*3/2

# 查看目前页最小阈值
sysctl -a|grep min_free_kbytes 
或者
cat /proc/sys/vm/min_free_kbytes 

# 修改
vi /etc/sysctl.conf
vm.min_free_kbytes = 409600
# 生效
sysctl -p /etc/sysctl.conf

NUMA

NUMA ( Non-Uniform Memory Access )?是一种计算机内存架构,它允许多个处理器或处理器核心拥有自己的本地内存,同时所有处理器可以访问整个系统的内存。在这种架构下,访问本地内存的速度要快于访问远端内存。

对操作系统的影响

  1. 内存访问延迟:由于访问远端内存的延迟大于本地内存,操作系统需要优化内存分配策略,尽量将线程和数据分配到相同的处理器节点上,以减少内存访问延迟。
  2. 性能优化:操作系统需要考虑NUMA架构的特点,进行合理的进程和内存管理,以提升多核处理器的性能。

利用优势

  • 进程和内存亲和性:将访问相同数据的进程或线程绑定到相同的处理器节点上,可以减少内存访问延迟,提高程序性能。
  • 内存分配策略:使用操作系统提供的内存分配策略,如numactl工具,可以控制进程的内存分配,使其优先使用本地内存。

避免出现问题

  • 避免跨节点访问:尽量避免跨节点访问内存,因为这会导致性能下降。
  • 合理配置内存:在部署应用程序时,应考虑NUMA架构,合理配置每个节点的内存使用,以避免某些节点内存不足而频繁访问远端内存
  • 使用NUMA-aware应用程序:对于支持NUMA架构的应用程序,确保它们能够正确识别和处理NUMA环境。

相关配置

进程绑定示例

将进程program绑定到节点0的CPU和内存上,未测试过

numactl --cpunodebind=0 --membind=0 program

可能会出现主机内存充足,但是因为NUMA节点内存耗尽产生OOM异常的情况,所以需要评估内存使用量。

状态信息
/proc/zoneinfo ? ZONE信息

numactl -H

/proc/sys/vm/zone_reclaim_mode
  • 默认的 0,表示既可以从其他 Node 寻找空闲内存,也可以从本地回收内存
  • 1、2、4 表示只回收本地内存,2 表示可以回写脏数据回收内存,4表示可以用 Swap 方式回收内存

内存使用量

这个分两种,系统的内存使用量以及进程的内存使用量

系统内存使用量

数据主要来自 /proc/meminfo 文件,就是不同软件显示的计算方式不太一样,不同版本也有所区别

一些查看系统内存使用情况的命令:

top 内存关注

avail Mem(可用内存)

  • 第二行的 avail Mem 是新应用可以直接使用且无需交换的物理内存,是可回收的缓存页和内存片
  • It is available on kernels 3.14, emulated on kernels 2.6.27+,otherwise the same as free.
  • 这表示系统当前可用的内存量,即未使用的内存加上缓存和缓冲区内存。
  • 这个数值可以帮助我们了解系统还有多少内存空间可以分配给新的进程或用于缓存数据

VIRT(虚拟内存大小):

  • 表示进程的虚拟内存大小,包括了进程申请的所有内存,不论是否实际使用了物理内存。
  • VIRT?通常会比?RES?大,因为虚拟内存包括了进程可能使用的内存空间的总和,包括未映射或未使用的内存区域
  • 任务使用的虚拟内存总量,包括所有代码、数据和共享库,以及已交换的页面和已映射但未使用的内存页

RES(常驻内存大小):

  • 表示进程实际使用的物理内存大小,不包括交换空间(swap)和共享内存。
  • RES?是实际占用内存的量,这个数值可以帮助我们了解进程对物理内存的消耗

SHR(共享内存大小):

  • 表示进程使用的共享内存大小,包括与其他进程共享的内存区域,如程序的代码段和动态链接库等。
  • SHR?并不一定是真正的“共享”内存,它也包括了进程独有的只读内存段

关联关系:

  • VIRT?=?RES?+?SHR?+ 未使用的虚拟内存空间
  • avail Mem?通常会受到?RES?和缓存的影响,因为当系统需要更多物理内存时,可能会牺牲缓存来提供更多的可用内存

作用:

  • 系统的整体内存使用情况(通过?avail Mem
  • 每个进程占用的虚拟内存空间(通过?VIRT
  • 每个进程实际使用的物理内存(通过?RES
  • 每个进程使用的共享内存量(通过?SHR

free 内存关注

man free
total      Total installed memory (MemTotal and SwapTotal in /proc/meminfo)
used       Used memory (calculated as total - free - buffers - cache)
free       Unused memory (MemFree and SwapFree in /proc/meminfo)
shared     Memory used (mostly) by tmpfs (Shmem in /proc/meminfo)
buffers    Memory used by kernel buffers (Buffers in /proc/meminfo)
cache      Memory used by the page cache and slabs (Cached and SReclaimable in /proc/meminfo)
buff/cache  Sum of buffers and cache
available    无需交换的可用于启动新应用的内存;考虑了page cache 以及并非所有可回收内存都会被回收

vmstat 内存关注

vmstat 5 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st

man vmstat
r: The number of runnable processes (running or waiting for run time).
b: The number of processes blocked waiting for I/O to complete.

单位 KB
swpd: the amount of virtual memory used.
free: the amount of idle memory.
buff: the amount of memory used as buffers.
cache: the amount of memory used as cache.
inact: the amount of inactive memory.  (-a option)
active: the amount of active memory.  (-a option)

sar 内存关注

很详细,但是太多了,man sar 找到-r 参数,看看

sar -r 5 5

/proc/meminfo 内存关注

cat /proc/meminfo | grep -E 'MemTotal|MemFree|MemAvailable|Buffers|Cached|SwapCached|SwapTotal|SwapFree'

MemTotal: 总内存大小,即物理内存的总容量

MemFree: 当前未使用的内存量

MemAvailable: 可用内存的估计值,这是一个更现代的内存计算指标,它试图反映出在不进行交换的情况下,系统可以使用的内存数量

Buffers: 内核缓冲区缓存的大小,这些缓冲区用于缓存磁盘上的块设备I/O操作

Cached: 页缓存的大小,即被内核缓存的数据大小,页缓存用于缓存文件系统的数据,提高文件访问速度

SwapCached: 缓存在交换区的内存量,当物理内存不足时,系统会将一些内存页交换到硬盘上的交换区,这个指标可以帮助我们了解有多少内存页当前在交换区

SwapTotalSwapFree: 交换区的总大小和空闲大小

进程内存使用量

一些查看进程内存使用情况的命令:

top 和 ps 的内存信息,可以参考前面的内存描述

ps axu
top

pidstat 内存关注

pidstat -r 5 5        # 统计5秒内的内存信息,统计5次
pidstat -r -p <PID> 1 3 # 统计1秒内,PID 进程的内存情况,统计3次

04:14:48 PM   UID       PID  minflt/s  majflt/s     VSZ     RSS   %MEM  Command

minflt/s:任务每秒发生的小错误(次要错误)总数,这些错误不需要从磁盘加载内存页

例如,当进程访问一个已经映射到内存但尚未加载到物理内存的页面时会发生页缺失(page fault),内核会从交换区(swap)或缓冲区(buffer)中获取页面。

majflt/s:任务每秒发生的主要错误总数,这些错误需要从磁盘加载内存页

分析

性能诊断:如果 minflt/smajflt/s 的值很高,可能表明进程正在面临内存压力,特别是在 majflt/s 高的情况下,可能会导致系统的磁盘I/O压力增加,进而影响整体性能。

资源监控:通过监控这些指标,系统管理员可以识别哪些进程可能导致内存不足,从而需要优化程序代码或增加系统内存。

故障排除:在诊断内存泄漏或内存使用不当的情况时,这些指标可以帮助定位问题进程。

系统调优:在调优系统时,降低 majflt/s 的值是一个目标,因为它可以减少磁盘I/O,提高系统响应速度。


缓存与缓存区命中率

Buffer 是对磁盘数据的缓存,而 Cache 是文件数据的缓存,它们既会用在读请求中,也会用在写请求中。缓存命中率高,就能减少速度慢的硬盘IO,提升系统性能。

内存泄露

  • 栈内存由系统自动分配和管理。一旦程序运行超出了这个局部变量的作用域,栈内存就会被系统自动回收,所以不会产生内存泄漏的问题
  • 堆内存由应用程序自己来分配和管理。除非程序退出,这些堆内存并不会被系统自动释放,而是需要应用程序明确调用库函数 free() 来释放它们,会有可能发生内存泄露
  • 内存映射段 ,其中共享内存由程序动态分配和管理,就有可能会发生内存泄露
文章来源:https://blog.csdn.net/weixin_43839586/article/details/135679363
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。