Правильне визначення використання пам'яті в Linux


63

Я трохи розгублений у деяких результатах, які я бачу від ps та безкоштовно .

На моєму сервері це результат 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 управляє пам'яттю, полягає в тому, що він зберігатиме використання диска в оперативній пам'яті, щоб кожен наступний доступ був швидшим. Я вважаю, що на це вказують "кешовані" стовпці. Крім того, різні буфери зберігаються в оперативній пам'яті, зазначеній у колонці "буфери".

Отже, якщо я правильно розумію, "фактичним" використанням повинно бути "використано" значення "- / + буфери / кеш", або 561 в цьому випадку.

Тож припускаючи, що все це правильно, частина, яка мене кидає, - це результати ps aux.

Моє розуміння psрезультатів полягає в тому, що шостий стовпець (RSS) представляє розмір у кілобайтах, який процес використовує для пам'яті.

Отже, коли я запускаю цю команду:

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

Чи не повинен результат бути "використаним" стовпцем "- / + буфери / кеш" з free -m?

Отже, як я можу правильно визначити використання пам'яті процесу в Linux? Мабуть, моя логіка хибна.


Це питання досить популярне, і я думаю, що мені слід поділитися відповіддю htopавтора на одне подібне запитання, яке було у мене днями ... Як обчислити використання пам'яті з / proc / meminfo (як htop)
tgogos

Відповіді:


57

Це саме таке питання було задано на сервері за замовчуванням просто днями :-)

Система віртуальної пам'яті Linux не така вже й проста. Ви не можете просто скласти всі поля RSS і отримати значення, про usedяке повідомляє free. Причин для цього багато, але я потраплю на пару найбільших.

  • Коли процес розщедриться, і батько, і дитина покажуть однаковий RSS. Однак linux працює copy-on-writeтак, що обидва процеси реально використовують однакову пам'ять. Тільки коли один з процесів модифікує пам'ять, він насправді буде дублюватися. Таким чином, це призведе freeдо меншої кількості topRSS-суми.

  • Значення RSS не включає спільну пам'ять. Оскільки спільна пам'ять не належить жодному процесу, topне включає її в RSS. Таким чином, це призведе до того, що freeкількість буде більшим, ніж topсума RSS.


1
Це найкраща відповідь, яку я отримав на будь-якому сайті обміну стеками на сьогоднішній день. Так конкретно, що я хотів знати. Це дуже точно в моїй ситуації, тому що я маю справу з програмою, яку я написав, що вилки процесів, але більшість слід у бібліотеках, якими вони користуються.
GoldenNewby

Проблема з цією відповіддю полягає в тому, що обчислення суми RSS і SHR часто дає набагато менше, ніж використана пам'ять. Наприклад, для VPS, який я маю, використовується пам'ять 380 Мб, тоді як сума всіх RSS і SHR становить 90 МБ.
користувач239558

2
@ user239558 Як я вже згадував у відповіді, є багато причин, за якими цифри не складаються, я перерахував лише 2 з них. Є багато інших чисел; кеш, плита, величезні сторінки тощо
Патрік

2
Можливо, через роки після того, як ти відповів на це, у мене все ще є (принаймні) одна плутанина. Ви сказали, що значення RSS не включає спільну пам'ять, але ця відповідь сказала, що "вона включає пам'ять із спільних бібліотек, поки сторінки з цих бібліотек насправді є в пам'яті". Зараз я не знаю, кому повірити ... Можливо, тут я пропускаю деякі тонкі відмінності ...
Naitree

1
@Naitree "спільні бібліотеки"! = "Спільна пам'ять". спільна пам'ять - це такі, як shmgetабо mmap. Формулювання навколо пам’яті дуже складне. Використання неправильного слова в неправильному місці може повністю викрутити значення речення.
Патрік

30

Якщо ви шукаєте номери пам'яті, які складаються, подивіться на smem :

smem - це інструмент, який може давати численні звіти про використання пам'яті в системах Linux. На відміну від існуючих інструментів, smem може повідомляти пропорційний заданий розмір (PSS), що є більш значущим поданням обсягу пам'яті, що використовується бібліотеками та програмами у віртуальній системі пам'яті.

Оскільки великі частини фізичної пам'яті зазвичай діляться між декількома додатками, стандартний показник використання пам'яті, відомий як розмір набору резидентів (RSS), значно завищить використання пам'яті. Натомість PSS вимірює "справедливу частку" кожної спільної області для надання реальної міри.

Наприклад тут:

# 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 

Це PSSцікавий стовпчик тут, оскільки він враховує спільну пам'ять.
На відміну від RSSцього доцільно додавати його. Тут ми отримуємо загалом 654 Мб для процесів користувача.

Загальносистемний вихід розповідає про решту:

# 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 

Таким чином, 1 Гб оперативної пам’яті загалом = 654 Мб оброблюваної програми + 346 Мб ядра пам’яті + 16 Мб безкоштовно
(надайте або візьміть кілька Мб)

В цілому приблизно половина пам'яті використовується для кешу (494Mb).

Бонусне питання : що тут кеш userland vs кеш ядра?


btw для чогось візуального спробуйте:

# smem  --pie=name

введіть тут опис зображення


14

Дійсно хорошим інструментом є pmapперелік поточного використання пам'яті для певного процесу:

pmap -d PID

Для отримання додаткової інформації про нього див. Сторінку man, man pmapа також ознайомтеся з 20 інструментами моніторингу системи Linux. Кожен SysAdmin повинен знати , у якому перераховані чудові інструменти, які я завжди використовую для отримання інформації про мою скриньку Linux.


Це досить класний інструмент, але він насправді не вирішує мою проблему. Я намагаюся розібратися, як ефективно визначити "фактичне" використання пам'яті на сервері.
GoldenNewby

3
@GoldenNewby Не існує такого поняття, як "фактичне" використання пам'яті процесу. Фактичне використання пам'яті системи - це те, що freeвам підказує.
Жиль

pmap -x PIDтакож включає стовпчик RSS, який часто буває досить корисним, щоб зрозуміти, звідки суть RSS процесу (як це спостерігається, наприклад, через via top).
maxschlepzig

10

Запустіть верх, натисніть hна допомогу, потім fдодайте поля. Ви можете додати такі поля:

  • RSS кількість фізичної пам'яті, яку використовує програма
  • CODE загальний об'єм пам'яті, який використовує виконуваний код процесу
  • DATA - загальний об'єм пам'яті (кб), виділений для даних процесу та стеку

Між цими 3 ви повинні мати досить точні результати. Ви також можете використовувати більш детальні заміни для верхнього я рекомендую htopабо atop.

Редагувати: Майже забули, якщо ви хочете дійсно детальну інформацію. Знайдіть PID та вкажіть наступний файл.

PID=123

cat /proc/123/status

Редагувати 2: Якщо ви можете знайти її чи мати її книгою:

Оптимізація продуктивності Linux: практичне керівництво інструментами для роботи Linux

-в розділі Розділ 5: Інструменти продуктивності: Пам'ять, що залежить від процесу, - це набагато більше інформації, ніж ви хотіли б.


У верхній частині за замовчуванням розмір RSS має процес. Вгорі дає однакові результати, як і "ps aux" у моєму прикладі. Моє запитання: як це, що комбінований RSS всіх процесів набагато вище, ніж "активне" використання пам'яті на всьому сервері?
GoldenNewby

5

psдає обсяг пам’яті, що використовується кожним процесом. Деяка частина цієї пам'яті є mmapped файлами, що рахується під кешем. Частина цієї пам’яті (особливо кодової) спільно використовується з іншими процесами, тому якщо ви додаєте значення RSS, вона підраховується кілька разів.

Немає правильної відповіді на те, "скільки пам'яті використовує цей процес?", Оскільки це не залежить від самого процесу, це також залежить від навколишнього середовища. Існує багато різних значень, які можна назвати процесом "використання пам'яті", і вони не відповідають або складаються, оскільки вони рахують різні речі.


4

Як правильно вказали інші, важко отримати обробку фактичної пам’яті, яка використовується процесом, що стосується спільних областей, а також файлів mmap'ed і чого іншого.

Якщо ви експериментатор, ви можете запускати валлінг і масив . Це може стати важким для випадкового користувача, але ви зрозумієте поведінку програми в пам'яті з часом. Якщо додаток malloc () саме те, що йому потрібно, це дасть вам гарне уявлення про реальне використання динамічної пам'яті процесу. Але цей експеримент можна «отруїти».

Щоб ускладнити справи, Linux дозволяє перевиконувати пам'ять. Коли ви malloc () пам'яті, ви заявляєте про свій намір споживати пам'ять. Але виділення насправді не відбувається, поки ви не напишете байт на нову сторінку виділеної "ОЗУ". Ви можете довести це собі, написавши та запустивши невелику програму на C:

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

Запустіть це на машині з меншою 16 Гб оперативної пам’яті і, вуаля !, ви щойно набрали 16 Гб пам’яті! (ні, не дуже).

Зауважте, що topви бачите "VIRT" як 16.004G, але% MEM - 0,0

Виконайте це знову за допомогою valgrind:

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

І масив каже "сума всіх алоків () = 16 ГБ". Тож це не дуже цікаво.

АЛЕ, якщо ви запускаєте його у розумному процесі:

# 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

І тут ми бачимо (дуже емпірично і з дуже високою впевненістю), що компілятор виділив 77 КБ купи.

Чому так важко намагатися отримати просто купівельне використання? Тому що всі спільні об’єкти та текстові розділи, які використовує процес (у цьому прикладі компілятор), не дуже цікаві. Вони постійні накладні витрати для процесу. Насправді, наступні виклики цього процесу майже виходять "безкоштовними".

Також порівняйте та порівняйте наступне:

MMAP () файл 1 Гб. Ваш VMSize становитиме 1 + ГБ. Але Ви розміром встановленого резидента будуть лише ті частини файлу, які ви спричинили для того, щоб бути створеними на сторінці (шляхом перенаправлення вказівника на цей регіон). І якщо ви "прочитали" весь файл тоді, до того часу, як ви досягнете кінця, ядро, можливо, вже започаткувало початки (це легко зробити, тому що ядро ​​точно знає, як / де замінити ці сторінки, якщо знову буде відзначено) ). В будь-якому випадку ні VMSize, ні RSS не є хорошим показником використання вашої пам'яті. Ви фактично нічого не malloc () не редагували.

Навпаки, Malloc () і торкніться ЛОТИ пам'яті - доки ваша пам'ять не перейде на диск. Тож ваша виділена пам'ять тепер перевищує ваш RSS. Тут ваш VMSize може почати щось вам повідомляти (ваш процес має більше пам’яті, ніж те, що насправді знаходиться у вашій ОЗУ). Але все ще важко розмежовувати VM, що використовується спільними сторінками, і VM, що обмінюється даними.

Тут стає цікавим вальгринд / масив. Він показує, що ви навмисно виділили (незалежно від стану ваших сторінок).


У мене є питання до вас. У мене є процес, який mlock () - це всі файли mmap'ed. Чи є спосіб визначити, яка частина цієї пам’яті активно використовується - скільки її прочитано або записано в, скажімо, минулу хвилину чи дві?
Майкл Мартінес

2

Спробуйте це: він дасть вам загальну оперативну пам’ять, фактично використану всіма процесами, що працюють в МБ

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}'

Про це sizeповідомляє psмало відношення до фактичного використання пам'яті. Це віртуальний розмір кожного процесу, який не обов'язково виділяється пам'яттю. Він також не включає деякі сегменти, які виділяються.
Метт

-2

Він покаже вам, скільки користувачів пам'яті користувачі ..

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

Використовуйте цю команду, щоб знайти використання пам'яті у%.

Використовувана пам'ять:

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

вільна пам'ять

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

3
Помилка, це нічого не дасть. grepбуде просто сидіти там і чекати введення.
mattdm

1
Це мало бутиfree -m | grep Mem | awk '{print $3/$2 * 100.0}'
vjangus
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.