Linux'ta bellek kullanımını doğru belirleme


63

PS ve ücretsiz gördüğüm bazı sonuçlarda kafam biraz karıştı .

Sunucumda bu, sonucudur free -m

[root@server ~]# free -m
             total       used       free     shared    buffers     cached
Mem:          2048       2033         14          0         73       1398
-/+ buffers/cache:        561       1486
Swap:         2047         11       2036

Linux'un belleği nasıl yönettiğini anladığım için, disk kullanımını RAM'de saklayacağı ve ardından her erişimin daha hızlı olacağı yönünde. Bunun "önbellek" sütunlarıyla gösterildiğine inanıyorum. Ek olarak, çeşitli tamponlar "tamponlar" sütununda belirtilen RAM'de saklanır.

Bu yüzden, doğru anlarsam, "gerçek" kullanımın "- / + buffers / cache" "kullanılmış" değeri veya bu durumda 561 olduğu varsayılır.

Tüm bunların doğru olduğunu varsayarsak, beni fırlatan kısım bunun sonucudur ps aux.

psSonuçları anladığım kadarıyla , 6. sütunun (RSS), işlemin hafıza için kullandığı kilobayt cinsinden boyutu temsil ettiği belirtiliyor.

Yani bu komutu çalıştırdığımda:

[root@server ~]# ps aux | awk '{sum+=$6} END {print sum / 1024}'
1475.52

Sonuç, "- / + buffers / cache" öğesinin "kullanılmış" sütunu değil free -mmidir?

Peki, bir işlemin bellek kullanımını Linux'ta nasıl doğru bir şekilde belirleyebilirim? Görünüşe göre mantığım hatalı.


Bu soru oldukça popüler ve sanırım htopyazarın cevabını geçen gün sahip olduğum benzer bir soruyla paylaşmalıyım ... / proc / meminfo'dan bellek kullanımı nasıl hesaplanır (htop gibi)
tgogos

Yanıtlar:


57

Bu tam aynı soruyu üzerinde istendi ServerFault Geçen gün :-)

Linux sanal bellek sistemi o kadar basit değil. Tüm RSS alanlarını ekleyemez ve rapor usededilen değeri elde edemezsiniz free. Bunun birçok nedeni var, ancak en büyüğüne birkaç tane vuracağım.

  • Bir süreç çatalladığında, hem ebeveyn hem de çocuk aynı RSS ile gösterilecektir. Ancak linux copy-on-write, iki işlemin de aynı belleği kullanması için kullanıyor. Sadece işlemlerden biri hafızayı değiştirdiğinde, aslında kopyalanacaktır. Bu, freesayının topRSS toplamından daha küçük olmasına neden olur .

  • RSS değeri paylaşılan hafızayı içermez. Paylaşılan hafıza herhangi bir işlem tarafından sahiplenilmediğinden top, RSS'ye dahil edilmez. Bu, freesayının topRSS toplamından daha büyük olmasına neden olur .


1
Bu, şu ana kadar herhangi bir borsa sitesinde aldığım en iyi cevap. Bu yüzden özellikle bilmek istediklerimi. Bu benim durumum için çok doğru, çünkü süreç çatallarının yazdığı bir programla uğraşıyorum, ama ayak izlerinin çoğunluğu kullandıkları kütüphanelerde.
GoldenNewby

Bu cevabın sorunu RSS ve SHR toplamını hesaplamanın çoğunlukla kullanılan hafızadan çok daha az vermesidir. Örneğin, sahip olduğum bir VPS'de, kullanılan bellek 380 MB, tüm RSS ve SHR toplamları 90 MB'dir.
user239558

2
@ user239558 Cevapta bahsettiğim gibi, rakamların artmamasının birçok nedeni var, sadece 2 tanesini listeledim. Bir sürü başka numara var; önbellek, döşeme, büyük sayfalar, vb.
Patrick

2
Muhtemelen yıllar sonra bunu cevapladıktan sonra, hala (en azından) bir kafa karışıklığım var. RSS değerinin paylaşılan hafızayı içermediğini söylediniz , ancak bu cevap "Bu kütüphanelerdeki sayfalar aslında bellekte olduğu sürece paylaşılan kütüphanelerdeki hafızayı içerir" demiştir. Şimdi hangisine inanacağımı bilmiyorum ... Belki burada bazı ince farkları
özlüyorum

1
@Naitree "paylaşılan kütüphaneler"! = "Paylaşılan hafıza". paylaşılan hafıza shmgetveya gibi şeylerdir mmap. Hafızanın etrafındaki ifadeler çok zor. Yanlış kelimeyi yanlış yerde kullanmak, cümlenin anlamını tamamen mahvedebilir.
Patrick,

30

Eklenen hafıza numaralarını arıyorsanız, smem'e bir göz atın :

smem, Linux sistemlerinde bellek kullanımı hakkında sayısız rapor verebilen bir araçtır. Mevcut araçların aksine, smem, sanal bellek sistemindeki kitaplıklar ve uygulamalar tarafından kullanılan bellek miktarının daha anlamlı bir temsili olan orantılı set boyutunu (PSS) bildirebilir.

Büyük fiziksel bellek bölümleri tipik olarak birden fazla uygulama arasında paylaşıldığından, yerleşik set boyutu (RSS) olarak bilinen standart bellek kullanımı ölçüsü, bellek kullanımını önemli ölçüde aşar. Bunun yerine PSS, her bir uygulamanın, paylaşılan alanın "adil payını" gerçekçi bir önlem almak üzere ölçer.

Örneğin burada:

# smem -t
  PID User     Command                         Swap      USS      PSS      RSS
...
10593 root     /usr/lib/chromium-browser/c        0    22868    26439    49364 
11500 root     /usr/lib/chromium-browser/c        0    22612    26486    49732 
10474 browser  /usr/lib/chromium-browser/c        0    39232    43806    61560 
 7777 user     /usr/lib/thunderbird/thunde        0    89652    91118   102756 
-------------------------------------------------------------------------------
  118 4                                       40364   594228   653873  1153092 

Öyleyse PSSburadaki ilginç sütun, paylaşılan hafızayı hesaba katmasıdır.
Aksine, RSSbunu eklemek anlamlıdır. Buradaki kullanıcı işlemleri için toplam 654Mb alıyoruz.

Sistem çapında çıktı geri kalanı anlatıyor:

# smem -tw
Area                           Used      Cache   Noncache 
firmware/hardware                 0          0          0 
kernel image                      0          0          0 
kernel dynamic memory        345784     297092      48692 
userspace memory             654056     181076     472980 
free memory                   15828      15828          0 
----------------------------------------------------------
                            1015668     493996     521672 

Yani 1 Gb RAM toplam = 654Mb userland işlemler + 346Mb çekirdek mem + 16Mb ücretsiz
(ver veya birkaç Mb al)

Genel olarak belleğin yaklaşık yarısı önbellek için kullanılır (494 Mb).

Bonus soru : Burada çekirdek önbellek vs userland önbellek nedir?


görsel bir şey denemek için btw:

# smem  --pie=name

görüntü tanımını buraya girin


14

pmapBelli bir işlem için mevcut hafıza kullanımını listeleyen gerçekten iyi bir araçtır :

pmap -d PID

Bu konuda daha fazla bilgi için man sayfasına bakın man pmapve aynı zamanda 20 Linux Sistem İzleme Araçlarına bakın .


Bu oldukça havalı bir araç, ancak sorunumu gerçekten çözmüyor. Sunucudaki "gerçek" bellek kullanımını nasıl etkili bir şekilde belirleyeceğimi bulmaya çalışıyorum.
GoldenNewby

3
@GoldenNewby Bir işlemin “gerçek” bellek kullanımı gibi bir şey yoktur. Sistemin gerçek bellek kullanımı freesize söylenen şeydir .
Gilles

pmap -x PIDayrıca bir sürecin RSS toplamının nerede olduğu hakkında fikir edinmek için genellikle oldukça yararlı olan bir RSS sütunu içerir (örneğin, üzerinden gözlemlendiği gibi top).
maxschlepzig

10

Çalıştırın, hyardım için vurun ve sonra falan ekleyin aşağıdaki alanları ekleyebilirsiniz:

  • RSS uygulamanın kullandığı fiziksel bellek
  • CODE işlemin yürütülebilir kodunun kullandığı toplam bellek miktarı
  • DATA - bir işlem verisine ve yığına tahsis edilmiş toplam bellek (kb)

Bu 3 arasında oldukça doğru sonuçlar almalısınız. Ayrıca tavsiye ederim htopya da tavsiye ederim üst için daha ayrıntılı yedek kullanabilirsiniz atop.

Düzenleme: Gerçekten ayrıntılı bilgi almak istiyorsanız neredeyse unuttum. PID'yi bulun ve aşağıdaki dosyayı yakalayın.

PID=123

cat /proc/123/status

Düzenleme 2: Eğer bulabilirseniz veya kitabı alabilirseniz:

Linux Performansını Optimize Etme: Linux Performans Araçlarına Uygulamalı Bir Rehber

-bir bölüm var Bölüm 5: Performans Araçları: İşleme Özel Bellek


Eh, varsayılan olarak sürecin RSS boyutuna sahiptir. Top benim örneğimde "ps aux" ile aynı sonuçları veriyor. Sorum şu, tüm işlemlerin birleşik RSS'sinin tüm sunucudaki "etkin" bellek kullanımından çok daha yüksek olması nasıl?
GoldenNewby

5

pssize her işlem tarafından kullanılan hafıza miktarını verir. Bu belleğin bir kısmı, önbellekte sayılan mmaplenmiş dosyalardır. Bu hafızanın bir kısmı (özellikle kod) diğer işlemlerle paylaşılır, bu nedenle RSS değerlerini eklerseniz, birden çok kez sayılır.

“Bu işlem ne kadar bellek kullanıyor?” İçin doğru bir cevap yok, çünkü yalnızca işleme bağlı değil, aynı zamanda çevreye de bağlı. İşlemin “bellek kullanımı” olarak adlandırabileceğiniz birçok farklı değer vardır ve farklı şeyler saydıkları için eşleşmez veya eklemezler.


4

Diğerlerinin doğru bir şekilde belirttiği gibi, bir işlem tarafından kullanılan gerçek bellek, paylaşılan bölgeler ve mmap'ed dosyaları ile ne olduğu ile ilgili bir işlem yapmak zor.

Deneyci iseniz valgrind ve massif çalıştırabilirsiniz . Bu, sıradan kullanıcılar için biraz ağır olabilir, ancak bir uygulamanın zaman içindeki belleği hakkında bir fikir edinebilirsiniz. Eğer bir uygulama malloc () tam olarak neye ihtiyacı varsa o zaman bu size bir işlemin gerçek dinamik bellek kullanımının iyi bir gösterimini verecektir. Ancak bu deney "zehirlenmiş" olabilir.

Meseleleri karmaşıklaştırmak için, Linux hafızanızı doldurmanıza izin verir . Malloc () hafızasında, hafıza kullanma niyetinizi belirtirsiniz. Ancak, tahsis edilen "RAM" inizin yeni sayfasına bir byte yazana kadar ayırma gerçekleşmez. Bunun gibi küçük bir C programı yazıp çalıştırarak bunu kendinize kanıtlayabilirsiniz:

// test.c
#include <malloc.h>
#include <stdio.h>
#include <unistd.h>
int main() {
    void *p;
    sleep(5)
    p = malloc(16ULL*1024*1024*1024);
    printf("p = %p\n", p);
    sleep(30);
    return 0;
}

# Shell:
cc test.c -o test && ./test &
top -p $!

Bunu 16GB'tan az RAM olan bir makinede çalıştırın ve işte !, 16GB bellek kazandınız! (hayır gerçek değil).

topSize dikkat edin: "VIRT" 16.004G, ancak% MEM 0.0

Bunu tekrar valgrind ile çalıştırın:

# Shell:
valgrind --tool=massif ./test &
sleep 36
ms_print massif.out.$! | head -n 30

Ve massif "bütün allocs toplamı () = 16GB" diyor. Yani bu çok ilginç değil.

AMA, eğer aklı başında bir süreçle çalıştırırsanız :

# Shell:
rm test test.o
valgrind --tool=massif cc test.c -o test &
sleep 3
ms_print massif.out.$! | head -n 30

--------------------------------------------------------------------------------
Command:            cc test.c -o test
Massif arguments:   (none)
ms_print arguments: massif.out.23988
--------------------------------------------------------------------------------


    KB
77.33^                                                                       :
     |                                                                      #:
     |                                                                :@::@:#:
     |                                                           :::::@@::@:#:
     |                                                         @:: :::@@::@:#:
     |                                                     ::::@:: :::@@::@:#:
     |                                             ::@:::@:::::@:: :::@@::@:#:
     |                                            @::@:::@:::::@:: :::@@::@:#:
     |                                            @::@:::@:::::@:: :::@@::@:#:
     |                      :@@@@@@@@@@@@@@@@@@@@:@::@:::@:::::@:: :::@@::@:#:
     |                      :@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                    :@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                    :@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                   :@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                   :@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |              :@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |          :::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |        :::::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |       ::::::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |       ::::::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
   0 +----------------------------------------------------------------------->Mi
     0                                                                   1.140

Ve burada görüyoruz ki (çok ampirik ve çok güvenli bir şekilde) derleyicinin 77KB yığın ayırdığını.

Neden sadece yığın kullanımı elde etmek için bu kadar çok deniyorsunuz? Çünkü bir işlemin kullandığı tüm paylaşılan nesneler ve metin bölümleri (bu örnekte, derleyici) çok ilginç değildir. Bir işlem için sabit giderler. Aslında, sürecin sonraki çağrıları neredeyse "özgür" geliyor.

Ayrıca, aşağıdakileri karşılaştırın ve karşılaştırın.

MMAP () 1 GB'lık bir dosya. VMSize'iniz 1 + GB olacaktır. Ancak, Resident Set Size yalnızca sayfalandırılmış olduğunuz dosyanın bölümleri olacaktır (bir işaretçiyi o bölgeye işaretleyerek). Ve eğer tüm dosyayı "okursanız", o zaman sona erdiğinde, çekirdek başlangıçta disk belleği eklemiş olabilir (çekirdekli kodlar yeniden tanımlanırsa bu sayfaları tam olarak nasıl / nerede değiştireceğini bildiği için ). Her iki durumda da, ne VMSize ne de RSS, hafızanızın "kullanımı" için iyi bir gösterge değildir. Aslında hiçbir şey yapmadın, malloc ().

Buna karşılık, Malloc () ve LOTS belleğe dokunun - belleğiniz diske geçene kadar. Böylece, tahsis edilmiş hafızanız şimdi RSS'inizi aşıyor Burada, VMSize'iniz size bir şey söylemeye başlayabilir (işleminiz RAM'inizde olduğundan daha fazla belleğe sahip). Ancak paylaşılan sayfalar olan VM ile değiştirilmiş veri olan VM arasında ayrım yapmak hala zor.

Valgrind / massif'in ilginçleştiği yer burasıdır. Size kasıtlı olarak neyi paylaştığınızı gösterir (sayfalarınızın durumuna bakılmaksızın).


Sana bir sorum var. Mlock () 'un hepsi mmap'lenmiş dosyaları olan bir işlemim var. Bu hafızanın ne kadarının aktif olarak kullanıldığını belirlemenin bir yolu var mı - geçmiş bir veya iki dakika içinde ne kadarının okunduğunu veya içine yazıldığını söylüyor?
Michael Martinez

2

Bunu dene: MB olarak çalışan tüm işlemler tarafından gerçekten kullanılan toplam RAM değerini verecektir.

ps -eo size,pid,user,command --sort -size | awk '
  { hr=$1/1024 ; printf("%13.2f Mb ",hr) } 
  { for ( x=4 ; x<=NF ; x++ ) { printf("%s ",$x) } print "" }
  ' | awk '{total=total + $1} END {print total}'

sizeTarafından bildirilen psasıl bellek kullanımının çok az ilişkisi vardır. Her işlemin mutlaka bellek ayırması gerekmeyen sanal boyutudur. Ayrıca tahsis edilen bazı bölümleri içermez.
Matt

-2

Kullanıcılar tarafından ne kadar hafıza kullanıcısı olduğunu gösterir.

#!/bin/bash
total_mem=0

printf "%-10s%-10s\n" User MemUsage

while read u m
do
        [[ $old_user != $u ]] && {  printf "%-10s%-0.1f\n" $old_user $total_mem;
                                    total_mem=0; }
        total_mem="$(echo $m + $total_mem | bc)"
        old_user=$u

done < <(ps --no-headers -eo user,%mem| sort -k1)

#EOF

-3

% 'Deki bellek kullanımını bulmak için bu komutu kullanın.

Kullanılan bellek:

grep Mem | awk '{print $3/$2 * 100.0}'

Boş hafıza

grep Mem | awk '{print $4/$2 * 100.0}'

3
Errr, bu hiçbir şey yapmaz. grepsadece orada oturup giriş için bekleyeceğim.
mattdm

1
Bu olmalıydıfree -m | grep Mem | awk '{print $3/$2 * 100.0}'
vjangus
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.