Bagaimana saya bisa mendapatkan jumlah memori yang tersedia secara portabel di seluruh distribusi?


12

File / alat standar yang melaporkan memori tampaknya memiliki format berbeda pada distribusi Linux yang berbeda. Misalnya, di Arch dan Ubuntu.

  • Lengkungan

    $ 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
    

Jadi, bagaimana saya bisa dibawa-bawa (hanya di distro Linux saja) dan secara andal mendapatkan jumlah memori — tidak termasuk swap — yang tersedia untuk digunakan oleh perangkat lunak saya pada waktu tertentu? Mungkin itulah yang ditampilkan sebagai "tersedia" dan "MemAvailable" di output freedan cat /proc/meminfodi Arch tetapi bagaimana cara mendapatkan yang sama di Ubuntu atau distribusi lain?

Jawaban:


18

MemAvailabletermasuk dalam /proc/meminfoversi 3.14 dari kernel; itu ditambahkan oleh komit 34e431b0a . Itulah faktor penentu dalam variasi output yang Anda tunjukkan. Pesan komit menunjukkan bagaimana memperkirakan memori yang tersedia tanpa MemAvailable:

Saat ini, jumlah memori yang tersedia untuk beban kerja yang baru, tanpa mendorong sistem ke swap, dapat diperkirakan dari MemFree, Active(file), Inactive(file), dan SReclaimable, serta "rendah" watermark dari /proc/zoneinfo.

Tanda air rendah adalah tingkat di mana sistem akan bertukar. Jadi dengan tidak adanya MemAvailableAnda setidaknya bisa menambah nilai yang diberikan untuk MemFree, Active(file), Inactive(file)dan SReclaimable(mana yang di masa sekarang /proc/meminfo), dan kurangi watermark rendah dari /proc/zoneinfo. Yang terakhir ini juga mencantumkan jumlah halaman gratis per zona, yang mungkin berguna sebagai perbandingan ...

Algoritma lengkap diberikan dalam tambalan meminfo.cdan tampaknya cukup mudah untuk beradaptasi:

  • jumlah tanda air rendah di semua zona;
  • ambil memori bebas yang diidentifikasi ( MemFree);
  • kurangi tanda air rendah (kita harus menghindari menyentuh itu untuk menghindari pertukaran);
  • tambahkan jumlah memori yang dapat kita gunakan dari cache halaman (jumlah Active(file)dan Inactive(file)): itu adalah jumlah memori yang digunakan oleh cache halaman, minus setengah dari cache halaman, atau tanda air rendah, mana yang lebih kecil;
  • tambahkan jumlah memori yang dapat kami klaim kembali ( SReclaimable), dengan mengikuti algoritma yang sama.

Jadi, dengan menggabungkan semua ini, Anda bisa mendapatkan memori yang tersedia untuk proses baru dengan:

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 

Ah, bagus, jadi setidaknya harus portable di versi kernel yang sama. Itu sesuatu. Saya menguji saran Anda dengan 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/meminfoyang seharusnya memberi saya nomor yang sama dicetak dua kali. Namun, angka kedua (pemahaman saya tentang algoritma yang Anda sarankan) lebih tinggi dari yang MemAvailableditunjukkan pada /proc/meminfo. Apa yang saya lakukan salah?
terdon

2
/proc/zoneinfomenghitung halaman, yang sebagian besar berukuran 4KB aktif amd64; Anda juga kehilangan keamanan tambahan yang ditambahkan ke cache halaman dan memori yang dapat diterima kembali. Menyederhanakan yang terakhir, kita dapat mengurangi tanda air rendah tiga kali, jadi m-12*low(3 × 4KB) memberikan hasil yang benar pada sistem saya. (Penyederhanaan ini meremehkan memori yang tersedia jika cache halaman atau memori yang dapat direklamasi lebih kecil dari dua kali tanda air rendah, tetapi Anda tetap tidak ingin menggunakan banyak memori dalam situasi itu sehingga tampaknya merupakan kompromi yang masuk akal.)
Stephen Kitt

1
@StephenKitt bagaimana Anda akan menghitungnya untuk kernel lama yang tidak memiliki (file)entires atau SReclaimableentri? Pada kotak centos yang lebih lama dengan kernel v 2.6.18-348.16.1.el5xen (per uname -r) ini adalah output yang saya dapatkan: pastebin.com/iFWiM1kX . Perhitungan Anda hanya menarik MemFreebagiannya
Mitch

@Mitch Saya tidak tahu, saya tidak yakin informasi yang tersedia dari kernel lama Anda cukup untuk menentukan memori yang tersedia (sebelum bertukar) secara akurat.
Stephen Kitt

Terima kasih kepada semua orang yang berkontribusi pada utas ini, ini merupakan referensi yang bagus. Perhitungan MemAvailable telah sedikit disesuaikan di Linux 4.5. Namun perhitungan MemAvailable baru harus selalu sedikit lebih tinggi dari (atau mungkin sama dengan) yang lama, jadi harus aman untuk menggunakan perhitungan lama dalam semua kasus. gitlab.com/procps-ng/procps/issues/42
sourcejedi

7

Sementara jawaban Stephen cukup sempurna dan salah di sisi hati-hati, saya memutuskan untuk menulis logika lengkap termasuk perbandingan minimum. Informasi pertama kali dibaca dari / proc / meminfo dan disimpan dalam variabel sehingga detail memori konsisten.

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

Hasil yang disimpan dalam variabel adalah dalam byte.


Sementara jawaban ini mengimplementasikan perhitungan dalam komi 34e431b0a, jawaban Stephen Kitt memberikan perkiraan yang lebih akurat pada 2 mesin dari 5 yang saya uji. Pada semua 5 mesin, kedua jawaban memberikan perkiraan yang lebih besar daripada MemAvailable dibaca langsung dari / proc / meminfo. Mungkin cara yang lebih aman adalah dengan mendapatkan yang lebih kecil antara 2, dan kalikan dengan 0,95 atau lebih.
toddwz
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.