Dağıtımlarda taşınabilir bellek miktarını nasıl taşınabilir olarak alabilirim?


12

Belleği bildiren standart dosyalar / araçlar, farklı Linux dağıtımlarında farklı biçimlere sahip gibi görünmektedir. Örneğin, Arch ve Ubuntu'da.

  • kemer

    $ 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
    

Peki, yazılımımın belirli bir zamanda kullanabileceği portatif olarak (yalnızca Linux dağıtımlarında) ve takas hariç bellek miktarını nasıl güvenilir bir şekilde alabilirim? Muhtemelen Arch çıktısında freeve Arch'de "kullanılabilir" ve "MemAvailable" olarak gösterilen şey budur, cat /proc/meminfoancak Ubuntu'da veya başka bir dağıtımda bunu nasıl alabilirim?

Yanıtlar:


18

MemAvailable/proc/meminfoçekirdeğin 3.14 sürümünden beri dahil edilmiştir ; taahhüt 34e431b0a ile eklendi . Gösterdiğiniz çıktı varyasyonlarında belirleyici faktör budur. Tamamlama mesajı, kullanılabilir hafızanın nasıl tahmin edileceğini gösterir MemAvailable:

Şu anda, takas içine sistemini iterek olmadan yeni iş yükü için kullanılabilir bellek miktarı, tahmin edilebilir MemFree, Active(file), Inactive(file), ve SReclaimable, hem de "düşük" filigran dan /proc/zoneinfo.

Düşük filigranlar, sistemin altında değiştirilecek düzeydir. Yani yokluğunda MemAvailablesize en azından için verilen değerler ekleyebilirsiniz MemFree, Active(file), Inactive(file)ve SReclaimable(mevcut in güvenliğine sahip hangisi /proc/meminfo) ve düşük filigran çıkarmak /proc/zoneinfo. İkincisi ayrıca, bir karşılaştırma olarak yararlı olabilecek bölge başına boş sayfa sayısını da listeler ...

Komple algoritma yamada verilmiştir meminfo.cve uyarlanması oldukça kolaydır:

  • tüm bölgelerdeki düşük filigranları toplamak;
  • belirlenen boş belleği al ( MemFree);
  • düşük filigranı çıkarın (takas etmemek için buna dokunmaktan kaçınmamız gerekir);
  • sayfa önbelleğinden kullanabileceğimiz bellek miktarını ekleyin ( Active(file)ve toplamı Inactive(file)): sayfa önbelleği tarafından kullanılan bellek miktarı, eksi sayfa önbelleğinin yarısı veya düşük filigran, hangisi daha küçükse;
  • SReclaimableaynı algoritmayı izleyerek geri alabileceğimiz ( ) bellek miktarını ekleyin .

Böylece, tüm bunları bir araya getirerek, hafızayı yeni bir işlem için kullanılabilir hale getirebilirsiniz:

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, güzel, en azından aynı çekirdek sürümü boyunca taşınabilir olmalı. Bu bir şey. 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/meminfoBana iki kez basılmış aynı sayı vermelidir önerinizi test ediyorum . Ancak, ikinci sayı (önerdiğiniz algoritmayı anladığım), MemAvailablegösterilenden daha yüksek /proc/meminfo. Neyi yanlış yapıyorum?
terdon

2
/proc/zoneinfoçoğunlukla 4KB boyutundaki sayfaları sayar amd64; sayfa önbelleğine eklenen ek güvenliği ve geri kazanılabilir belleği de kaçırıyorsunuz. İkincisini basitleştirerek, düşük filigranı üç kez çıkarabiliriz, böylece m-12*low(3 × 4KB) sistemimde doğru sonucu verir. (Sayfa önbelleği veya geri kazanılabilir bellek, düşük filigranın iki katından küçükse bu basitleştirme kullanılabilir belleği hafife alır, ancak bu durumda zaten çok fazla bellek kullanmak istemezsiniz, bu da makul bir uzlaşma gibi görünüyor.)
Stephen Kitt

1
@StephenKitt girişi (file)ya da SReclaimablegirişi olmayan eski çekirdekler için hesaplamayı nasıl yapardınız ? Çekirdek v 2.6.18-348.16.1.el5xen (per uname -r) ile daha eski bir centos kutusunda bu çıktı alıyorum: pastebin.com/iFWiM1kX . Hesaplamanız sadece MemFreeparçayı çekiyor
Mitch

@Mitch Bilmiyorum, eski çekirdeğinizde mevcut olan bilgilerin (değiştirmeden önce) kullanılabilir belleği belirlemek için yeterli olduğundan emin değilim.
Stephen Kitt

Bu konuya katkıda bulunan herkese teşekkürler, harika bir referans. MemAvailable hesaplaması Linux 4.5'te biraz ayarlanmıştır. Bununla birlikte, yeni MemAvailable hesaplaması her zaman eskisinden biraz daha yüksek (veya belki de aynı) olmalıdır, bu nedenle her durumda eski hesaplamayı kullanmak güvenli olmalıdır. gitlab.com/procps-ng/procps/issues/42
sourcejedi

7

Stephen'ın cevabı mükemmel bir şekilde yeterli ve dikkatli olunmasına rağmen, minimum karşılaştırmaları içeren tam mantığı yazmaya karar verdim. Bilgiler önce / proc / meminfo'dan okunur ve bellek ayrıntılarının tutarlı olması için bir değişkende saklanır.

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

Değişkende saklanan sonuç bayt cinsindendir.


Bu cevap 34e431b0a taahhüdündeki hesaplamayı uygularken, Stephen Kitt'in cevabı test ettiğim 5 makineden 2'sinde daha doğru bir tahmin sağladı. 5 makinenin hepsinde, her iki cevap da doğrudan / proc / meminfo'dan okunan MemAvailable'dan daha büyük tahminler verdi. Muhtemelen daha güvenli bir yol, 2 arasında daha küçük elde etmek ve 0,95 ya da daha fazla çarpmaktır.
toddwz
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.