ディストリビューション間で移植可能なメモリの量をどのように取得できますか?


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や他のディストリビューションで同じようにするにはどうすればよいですか?

回答:


18

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 

ああ、いいので、少なくとも同じカーネルバージョン間で移植可能である必要があります。それは何かです。私はあなたの提案をテストしています。これにより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、同じ番号が2回印刷されます。ただし、2番目の数値(提案するアルゴリズムについての私の理解)は、にMemAvailable示されている数値よりも高くなっています/proc/meminfo。何が悪いのですか?
terdon

2
/proc/zoneinfoのサイズが主に4KBのページをカウントしますamd64。また、ページキャッシュと再生可能なメモリに追加された余分な安全性もありません。後者を単純化すると、最低水準点を3回差し引くことができるため、m-12*low(3×4KB)は私のシステムで正しい結果をもたらします。(この単純化は、ページキャッシュまたは再利用可能なメモリが最低水準点の2倍よりも小さい場合、使用可能なメモリを過小評価しますが、とにかくその状況で多くのメモリを使用したくないので、それは妥当な妥協と思われます。)
Stephen Kitt

1
@StephenKitt全体も(file)エントリもない古いカーネルの場合、どのように計算しSReclaimableますか?古いCentOSのカーネルV 2.6.18-348.16.1.el5xen(あたりでボックスのuname -r)これは私が手に出力されます:pastebin.com/iFWiM1kX。あなたの計算はMemFree部品を引っ張るだけです
Mitch

@Mitchわからない。古いカーネルから入手できる情報が、(スワップ前の)使用可能なメモリを正確に判断するのに十分かどうかはわかりません。
Stephen Kitt 2016年

このスレッドに貢献してくれた皆さんに感謝します。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

変数に格納される結果はバイト単位です。


この回答はコミット34e431b0aで計算を実装していますが、Stephen Kittの回答は、テストした5台のうち2台のマシンでより正確な見積もりを提供しました。5つのマシンすべてで、どちらの回答も、/ proc / meminfoから直接読み取ったMemAvailableよりも大きな見積もりを出しました。おそらくより安全な方法は、2の間の小さい方を取得し、0.95倍にすることです。
toddwz
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.