如何获得各个发行版之间可移植的可用内存量?


12

报告内存的标准文件/工具在不同的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
    
  • 的Ubuntu

    $ 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发行版)并可靠地获得可供软件在特定时间使用的内存量(不包括交换)?大概就是在Arch freecat /proc/meminfoArch 的输出中显示为“ available”和“ MemAvailable”的东西,但是我如何在Ubuntu或其他发行版中得到相同的呢?

Answers:


18

MemAvailable/proc/meminfo从内核3.14版本开始包含;由commit 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 

嗯,很好,因此至少它应该可以在同一内核版本中移植。就是这样 我正在测试您的建议awk -v low=$(grep low /proc/zoneinfo | awk '{k+=$2}END{print k}') '{a[$1]=$2}END{m=a["MemFree:"]+a["Active(file):"]+a["Inactive(file):"]+a["SReclaimable:"]; print a["MemAvailable:"],m-low}' /proc/meminfo,应该给我两次打印的相同数字。但是,第二个数字(我对您建议的算法的理解)高于中MemAvailable显示的/proc/meminfo。我究竟做错了什么?
terdon

2
/proc/zoneinfo计算页面,页面的大小大多为4KB amd64;您还缺少添加到页面缓存和可回收内存中的额外安全性。简化后者,我们可以减去低水印3倍,因此m-12*low(3×4KB)在我的系统上给出了正确的结果。(如果页面高速缓存或可回收内存小于低水位标记的两倍,这种简化会低估可用内存,但是无论如何您都不想在这种情况下使用太多内存,因此这似乎是一个合理的折衷。)
Stephen Kitt

1
@StephenKitt您将如何为没有(file)完整或SReclaimable条目的较旧内核计算它?在内核版本为2.6.18-348.16.1.el5xen(per uname -r)的较旧centos机器上,这是我得到的输出:pastebin.com/iFWiM1kX。您的计算仅能发挥MemFree作用
-Mitch

@Mitch我不知道,我不确定您旧内核中可用的信息是否足以准确确定可用内存(在交换之前)。
史蒂芬·基特

感谢所有对此线程做出贡献的人,它是一个很好的参考。在Linux 4.5中,对MemAvailable的计算已进行了一些调整。但是,新的MemAvailable计算应始终比旧计算高一点(或可能与之相同),因此在所有情况下使用旧计算应该是安全的。 gitlab.com/procps-ng/procps/issues/42
sourcejedi

7

尽管斯蒂芬的答案是完全足够的,但出于谨慎的考虑,我还是决定写下包括最小比较在内的全部逻辑。首先从/ 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

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


虽然此答案在commit 34e431b0a中实现了计算,但是Stephen Kitt的答案在我测试的5台机器中有2台提供了更准确的估计。在所有5台计算机上,与直接从/ proc / meminfo读取的MemAvailable相比,这两个答案给出的估计值都更大。可能更安全的方法是在2与2之间取较小的值,然后乘以0.95左右。
toddwz
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.