Menentukan penggunaan memori dengan benar di Linux

63

Saya agak bingung pada beberapa hasil yang saya lihat dari ps dan gratis .

Di server saya, ini adalah hasil dari 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

Pemahaman saya tentang bagaimana Linux mengelola memori, adalah bahwa ia akan menyimpan penggunaan disk dalam RAM, sehingga setiap akses selanjutnya lebih cepat. Saya percaya ini ditunjukkan oleh kolom "cache". Selain itu, berbagai buffer disimpan dalam RAM, ditunjukkan di kolom "buffer".

Jadi jika saya mengerti dengan benar, penggunaan "aktual" seharusnya menjadi nilai "bekas" dari "- / + buffer / cache", atau 561 dalam hal ini.

Jadi dengan asumsi semua itu benar, bagian yang melempar saya adalah hasil ps aux.

Pemahaman saya tentang pshasilnya, adalah bahwa kolom ke-6 (RSS), mewakili ukuran dalam kilobyte yang digunakan proses untuk memori.

Jadi ketika saya menjalankan perintah ini:

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

Bukankah seharusnya hasilnya berupa kolom "bekas" "- / + buffer / cache" dari free -m?

Jadi, bagaimana saya bisa menentukan dengan benar penggunaan memori dari suatu proses di Linux? Rupanya logika saya cacat.

GoldenNewby
sumber
Pertanyaan ini cukup populer dan saya pikir saya harus membagikan jawaban htoppenulis untuk satu pertanyaan serupa yang saya miliki
kemarin

Jawaban:

58

Ini sebenarnya pertanyaan yang sama diminta pada serverfault hanya beberapa hari :-)

Sistem memori virtual linux tidak begitu sederhana. Anda tidak bisa menambahkan semua kolom RSS dan mendapatkan nilai yang dilaporkan usedoleh free. Ada banyak alasan untuk ini, tetapi saya akan menemukan beberapa alasan terbesar.

  • Ketika sebuah proses bercabang, baik orang tua dan anak akan ditampilkan dengan RSS yang sama. Namun linux mempekerjakan copy-on-writesehingga kedua proses tersebut benar-benar menggunakan memori yang sama. Hanya ketika salah satu proses memodifikasi memori yang akan benar-benar diduplikasi. Jadi ini akan menyebabkan freejumlahnya lebih kecil dari topjumlah RSS.

  • Nilai RSS tidak termasuk memori bersama. Karena memori bersama tidak dimiliki oleh satu proses apa pun, toptidak termasuk dalam RSS. Jadi ini akan menyebabkan freejumlahnya menjadi lebih besar dari topjumlah RSS.

Patrick
sumber
1
Ini adalah jawaban terbaik yang pernah saya dapatkan di situs pertukaran-stack. Jadi secara spesifik apa yang ingin saya ketahui. Ini sangat akurat untuk situasi saya karena saya sedang berhadapan dengan sebuah program yang saya tulis yang memalsukan proses, tetapi sebagian besar jejak kaki ada di perpustakaan yang mereka gunakan.
GoldenNewby
Masalah dengan jawaban ini adalah bahwa menghitung jumlah RSS dan SHR sering memberikan jauh lebih sedikit daripada memori yang digunakan. Misalnya pada VPS yang saya miliki, memori yang digunakan adalah 380MB sedangkan jumlah semua RSS dan SHR adalah 90MB.
user239558
2
@ user239558 Seperti yang saya sebutkan dalam jawaban, ada banyak alasan angka-angka itu tidak bertambah, saya hanya mencantumkan 2 di antaranya. Ada banyak nomor lainnya; cache, slab, halaman besar, dll
Patrick
2
Mungkin bertahun-tahun kemudian setelah Anda menjawab ini, saya masih memiliki (setidaknya) satu kebingungan. Anda mengatakan bahwa nilai RSS tidak termasuk memori bersama, tetapi jawaban ini mengatakan bahwa "Ini termasuk memori dari pustaka bersama selama halaman dari pustaka tersebut sebenarnya ada dalam memori". Sekarang saya tidak tahu yang mana yang harus saya percaya ... Mungkin saya kehilangan beberapa perbedaan halus di sini ...
Naitree
1
@Naitree "perpustakaan bersama"! = "Memori bersama". memori bersama adalah hal-hal seperti shmgetatau mmap. Kata-kata di sekitar hal-hal memori sangat rumit. Menggunakan kata yang salah di tempat yang salah dapat benar-benar mengacaukan makna kalimat.
Patrick
30

Jika Anda mencari nomor memori yang bertambah, lihatlah smem :

smem adalah alat yang dapat memberikan banyak laporan tentang penggunaan memori pada sistem Linux. Tidak seperti alat yang ada, smem dapat melaporkan ukuran set proporsional (PSS), yang merupakan representasi yang lebih bermakna dari jumlah memori yang digunakan oleh perpustakaan dan aplikasi dalam sistem memori virtual.

Karena sebagian besar memori fisik biasanya dibagi di antara beberapa aplikasi, ukuran standar penggunaan memori yang dikenal sebagai resident set size (RSS) akan secara signifikan melebih-lebihkan penggunaan memori. Sebagai gantinya, PSS mengukur masing-masing aplikasi "bagian yang adil" dari masing-masing area yang dibagikan untuk memberikan ukuran yang realistis.

Sebagai contoh di sini:

# 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 

Begitu PSSjuga kolom yang menarik di sini karena mengambil memori bersama ke akun.
Tidak seperti RSSitu berarti menambahkannya. Kami mendapatkan total 654Mb untuk proses userland di sini.

Output seluruh sistem memberi tahu tentang sisanya:

# 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 

Jadi 1Gb RAM Total = 654Mb proses userland + 346Mb kernel mem + 16MB bebas
(memberi atau mengambil beberapa Mb)

Secara keseluruhan sekitar setengah dari memori digunakan untuk cache (494Mb).

Pertanyaan bonus : apakah cache userland vs cache kernel di sini?


btw untuk sesuatu yang coba visual:

# smem  --pie=name

masukkan deskripsi gambar di sini

perasan lemon
sumber
14

Alat yang sangat bagus adalah pmapyang mencantumkan penggunaan memori saat ini untuk proses tertentu:

pmap -d PID

Untuk informasi lebih lanjut tentang hal ini, lihat halaman manual man pmapdan lihatlah di 20 Alat Pemantau Sistem Linux yang Harus Diketahui Setiap SysAdmin , yang berisi daftar alat hebat yang selalu saya gunakan untuk mendapatkan informasi tentang kotak Linux saya.

ByteNudger
sumber
Itu alat yang sangat keren, tetapi itu tidak benar-benar menyelesaikan masalah saya. Saya mencoba mencari cara untuk secara efektif menentukan penggunaan memori "aktual" di server.
GoldenNewby
3
@GoldenNewby Tidak ada yang namanya penggunaan memori "aktual" dari suatu proses. Penggunaan memori sebenarnya dari sistem adalah apa yang freememberitahu Anda.
Gilles 'SO- stop being evil'
pmap -x PIDjuga termasuk kolom RSS yang sering sangat berguna untuk mendapatkan ide dari mana RSS jumlah suatu proses (seperti yang diamati misalnya via topberasal dari).
maxschlepzig
10

Jalankan atas, tekan huntuk bantuan lalu ftambahkan bidang. Anda dapat menambahkan bidang-bidang berikut:

  • RSS jumlah memori fisik yang digunakan aplikasi
  • CODE jumlah total memori yang dapat dieksekusi kode proses
  • DATA - jumlah total memori (kb) yang didedikasikan untuk data dan tumpukan proses

Antara 3 ini Anda harus memiliki hasil yang cukup akurat. Anda juga dapat menggunakan penggantian yang lebih rinci untuk bagian atas yang saya sarankan htopatau atop.

Sunting: Hampir lupa jika Anda ingin informasi yang sangat terperinci. Temukan PID dan cat file berikut.

PID=123

cat /proc/123/status

Sunting 2: Jika Anda dapat menemukannya atau memilikinya buku:

Mengoptimalkan Kinerja Linux: Panduan Praktis untuk Alat Kinerja Linux

-memiliki bagian Bab 5: Alat Kinerja: Memori Khusus-Proses-ini memiliki informasi yang jauh lebih banyak daripada yang Anda inginkan.

2bc
sumber
Yah top secara default memiliki ukuran proses RSS. Top memberikan hasil yang identik seperti halnya "ps aux" dalam contoh saya. Pertanyaan saya adalah, bagaimana RSS gabungan semua proses jauh lebih tinggi daripada penggunaan memori "aktif" di seluruh server?
GoldenNewby
5

psmemberi Anda jumlah memori yang digunakan oleh setiap proses. Sebagian dari memori itu adalah file mmapped, yang diperhitungkan dalam cache. Sebagian dari memori itu (terutama kode) dibagikan dengan proses lain, jadi jika Anda menambahkan nilai RSS, itu dihitung beberapa kali.

Tidak ada jawaban yang tepat untuk "berapa banyak memori yang digunakan proses ini?", Karena tidak tergantung pada proses saja, itu juga tergantung pada lingkungan. Ada banyak nilai yang berbeda yang Anda sebut "penggunaan memori" dari proses, dan mereka tidak cocok atau bertambah karena mereka menghitung hal yang berbeda.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
4

Seperti yang orang lain tunjukkan dengan benar, sulit untuk menangani memori aktual yang digunakan oleh suatu proses, apa dengan daerah yang dibagikan, dan file mmap'ed dan yang lainnya.

Jika Anda seorang eksperimen, Anda dapat menjalankan valgrind dan massif . Ini mungkin menjadi agak berat bagi pengguna biasa tetapi Anda akan mendapatkan gagasan tentang perilaku memori aplikasi dari waktu ke waktu. Jika sebuah aplikasi malloc () adalah persis apa yang dibutuhkannya maka ini akan memberi Anda representasi yang baik dari penggunaan memori dinamis nyata dari suatu proses. Tapi percobaan ini bisa "diracuni".

Untuk memperumit masalah, Linux memungkinkan Anda untuk membuat terlalu banyak ingatan. Saat Anda malloc () memori, Anda menyatakan niat Anda untuk mengkonsumsi memori. Tetapi alokasi tidak benar-benar terjadi sampai Anda menulis byte ke halaman baru dari "RAM" yang dialokasikan. Anda dapat membuktikan ini pada diri sendiri dengan menulis dan menjalankan program C kecil seperti:

// 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 $!

Jalankan ini pada mesin dengan kurang dari 16GB RAM dan, voila !, Anda baru saja mencetak 16GB memori! (tidak terlalu).

Perhatikan bahwa topAnda melihat "VIRT" sebagai 16,004G tetapi% MEM adalah 0,0

Jalankan ini lagi dengan valgrind:

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

Dan massif mengatakan "jumlah semua allocs () = 16GB". Jadi itu tidak terlalu menarik.

TAPI, jika Anda menjalankannya pada proses yang waras :

# 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

Dan di sini kita melihat (sangat empiris dan dengan keyakinan sangat tinggi) bahwa kompiler mengalokasikan 77KB tumpukan.

Mengapa berusaha sangat keras untuk mendapatkan hanya tumpukan penggunaan? Karena semua objek dan bagian teks yang digunakan bersama oleh suatu proses (dalam contoh ini, kompiler) tidak terlalu menarik. Mereka overhead konstan untuk suatu proses. Bahkan, doa selanjutnya dari proses tersebut hampir datang secara "gratis".

Juga, bandingkan dan kontraskan yang berikut ini:

MMAP () file 1GB. VMSize Anda akan menjadi 1 + GB. Tapi Anda Resident Set Size hanya akan menjadi bagian dari file yang Anda paging (dengan mendereferensi pointer ke wilayah itu). Dan jika Anda "membaca" seluruh file kemudian, pada saat Anda sampai di akhir, kernel mungkin sudah membuka awal (ini mudah dilakukan karena kernel tahu persis bagaimana / di mana untuk mengganti halaman-halaman itu jika direferensi lagi ). Dalam kedua kasus tersebut, baik VMSize maupun RSS bukanlah indikator yang baik untuk "penggunaan" memori Anda. Anda belum benar-benar malloc () melakukan sesuatu.

Sebaliknya, Malloc () dan sentuh LOTS memori - hingga memori Anda ditukar ke disk. Jadi memori yang dialokasikan sekarang melebihi RSS Anda. Di sini, VMSize Anda mungkin mulai memberi tahu Anda sesuatu (proses Anda memiliki lebih banyak memori daripada yang sebenarnya tersimpan di RAM Anda). Tetapi masih sulit untuk membedakan antara VM yang berbagi halaman dan VM yang bertukar data.

Di sinilah valgrind / massif menjadi menarik. Ini menunjukkan kepada Anda apa yang telah Anda alokasikan dengan sengaja (terlepas dari keadaan halaman Anda).

Miles F. Bintz II
sumber
Saya punya pertanyaan untuk Anda. Saya punya proses yang mlock () semua file itu mmap'ed. Apakah ada cara untuk menentukan berapa banyak memori ini digunakan secara aktif - berapa banyak memori yang sudah dibaca atau ditulis dalam, katakanlah, satu atau dua menit terakhir?
Michael Martinez
2

Coba ini: ini akan memberi Anda total RAM yang benar-benar digunakan oleh semua proses yang berjalan dalam MB

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}'
Vineeth
sumber
The sizedilansir psmemiliki sedikit hubungan dengan penggunaan memori yang sebenarnya. Ini adalah ukuran virtual dari setiap proses yang tidak perlu dialokasikan memori. Itu juga tidak termasuk beberapa segmen yang dialokasikan.
Matt
-2

Ini akan menunjukkan kepada Anda berapa banyak pengguna memori oleh pengguna ..

#!/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
Vinood NK Maheshwari
sumber
-3

Gunakan perintah ini untuk menemukan pemanfaatan memori dalam%.

Memori yang digunakan:

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

memori bebas

grep Mem | awk '{print $4/$2 * 100.0}'
Arjun K Mukundan
sumber
3
Errr, ini tidak akan melakukan apa pun. grephanya akan duduk di sana menunggu input.
mattdm
1
Ini seharusnyafree -m | grep Mem | awk '{print $3/$2 * 100.0}'
vjangus