如何跨发行版获取可移植的可用内存量?

如何跨发行版获取可移植的可用内存量?

报告内存的标准文件/工具在不同的 Linux 发行版上似乎有不同的格式。例如,在 Arch 和 Ubuntu 上。

  • $ free
                  total        used        free      shared  buff/cache   available
    Mem:        8169312     3870392     2648348       97884     1650572     4110336
    Swap:      16777212      389588    16387624
    
    
    $ head /proc/meminfo 
    MemTotal:        8169312 kB
    MemFree:         2625668 kB
    MemAvailable:    4088520 kB
    Buffers:          239688 kB
    Cached:          1224520 kB
    SwapCached:        17452 kB
    Active:          4074548 kB
    Inactive:        1035716 kB
    Active(anon):    3247948 kB
    Inactive(anon):   497684 kB
    
  • 乌班图

    $ free
                 total       used       free     shared    buffers     cached
    Mem:      80642828   69076080   11566748    3063796     150688   58358264
    -/+ buffers/cache:   10567128   70075700
    Swap:     20971516    5828472   15143044
    
    
    $ head /proc/meminfo 
    MemTotal:       80642828 kB
    MemFree:        11565936 kB
    Buffers:          150688 kB
    Cached:         58358264 kB
    SwapCached:      2173912 kB
    Active:         27305364 kB
    Inactive:       40004480 kB
    Active(anon):    7584320 kB
    Inactive(anon):  4280400 kB
    Active(file):   19721044 kB
    

那么,我如何可移植(仅限 Linux 发行版)并可靠地获取可供我的软件在特定时间使用的内存量(不包括交换区)?据推测,这就是 Archfree和Arch的输出中显示为“可用”和“MemAvailable”的内容,cat /proc/meminfo但如何在 Ubuntu 或其他发行版中获得相同的结果?

答案1

MemAvailable/proc/meminfo自 3.14 版内核起包含;它是由提交 34e431b0a。这是您显示的输出变化的决定因素。提交消息指示如何估计可用内存而无需MemAvailable

目前,在不将系统推入交换的情况下,可用于新工作负载的内存量可以根据MemFreeActive(file)Inactive(file)SReclaimable以及来自 的“低”水位线进行估计/proc/zoneinfo

低水位线是系统交换的级别。因此,在没有 的情况下,您至少可以将、和MemAvailable给出的值相加(以中存在的为准),并从 中减去低水位线。后者还列出了每个区域的可用页面数量,这可能有助于比较......MemFreeActive(file)Inactive(file)SReclaimable/proc/meminfo/proc/zoneinfo

完整的算法在补丁中给出,meminfo.c并且看起来相当容易适应:

  • 将所有区域的低水位线相加;
  • 获取已识别的空闲内存 ( MemFree);
  • 减去低水印(我们需要避免触及它以避免交换);
  • 添加我们可以从页面缓存使用的内存量( 和Active(file)Inactive(file):这是页面缓存使用的内存量,减去页面缓存的一半或低水位线,以较小者为准;
  • SReclaimable按照相同的算法添加我们可以回收的内存量 ( )。

因此,将所有这些放在一起,您可以通过以下方式获取可用于新进程的内存:

awk -v low=$(grep low /proc/zoneinfo | awk '{k+=$2}END{print k}') \
 '{a[$1]=$2}
  END{ 
   print a["MemFree:"]+a["Active(file):"]+a["Inactive(file):"]+a["SReclaimable:"]-(12*low); 
  }' /proc/meminfo 

答案2

尽管 Stephen 的回答非常充分,并且谨慎行事,但我还是决定写下完整的逻辑,包括最低限度的比较。首先从 /proc/meminfo 读取信息并将其存储在变量中,以使内存详细信息保持一致。

LOW_WATERMARK=$(awk '$1 == "low" {LOW_WATERMARK += $2} END {print LOW_WATERMARK * 4096}' /proc/zoneinfo)

MEMINFO=$(</proc/meminfo)

MEMINFO_MEMFREE=$(echo "${MEMINFO}" | awk '$1 == "MemFree:" {print $2 * 1024}')
MEMINFO_FILE=$(echo "${MEMINFO}" | awk '{MEMINFO[$1]=$2} END {print (MEMINFO["Active(file):"] + MEMINFO["Inactive(file):"]) * 1024}')
MEMINFO_SRECLAIMABLE=$(echo "${MEMINFO}" | awk '$1 == "SReclaimable:" {print $2 * 1024}')

MEMINFO_MEMAVAILABLE=$((
  MEMINFO_MEMFREE - LOW_WATERMARK
  + MEMINFO_FILE - ((MEMINFO_FILE/2) < LOW_WATERMARK ? (MEMINFO_FILE/2) : LOW_WATERMARK)
  + MEMINFO_SRECLAIMABLE - ((MEMINFO_SRECLAIMABLE/2) < LOW_WATERMARK ? (MEMINFO_SRECLAIMABLE/2) : LOW_WATERMARK)
))

if [[ "${MEMINFO_MEMAVAILABLE}" -le 0 ]]
then
  MEMINFO_MEMAVAILABLE=0
fi

存储在变量中的结果以字节为单位。

相关内容