LINUX.ORG.RU
ФорумAdmin

Помогите понять потребление памяти


0

2

Есть сервер с 1Гб памяти, и 512Мб свопом. Периодически java сервер убивается OOM Killer. Прямо перед этим событием atop показывает следующую картину:

MEM |  tot   987.5M |  free   54.7M |  cache  87.0M |  dirty   0.7M |  buff   10.4M  | slab   39.4M  |               |               |
SWP |  tot   512.0M |  free   12.3M |               |               |                |               | vmcom   1.4G  | vmlim   1.0G  |

  PID    MINFLT     MAJFLT     VSTEXT      VSIZE      RSIZE     VGROW      RGROW     RUID         EUID          MEM     CMD       
28966      1847        840         1K     938.6M     636.9M     1024K      8772K     webserve     webserve      64%     java
31968      1573         18     17358K       7.9G     51036K        0K       460K     mongodb      mongodb        5%     mongod
 5985     15357          5      5243K     50360K     30028K     1156K       740K     postgres     postgres       3%     postgres
 5984      2726         22      5243K     49072K     29432K        0K       192K     postgres     postgres       3%     postgres
 5824         0          0      5243K     49460K     29200K        0K         0K     postgres     postgres       3%     postgres
 5983      7872          0      5243K     49072K     28968K    -1348K      -784K     postgres     postgres       3%     postgres
 6140      5092          0      5243K     49072K     27864K        0K         0K     postgres     postgres       3%     postgres
 3469         0          0      5243K     47036K      9092K        0K         0K     postgres     postgres       1%     postgres
 3468         0          0      5243K     47036K      7196K        0K         0K     postgres     postgres       1%     postgres

Я знаю какие процессы доедают оставшуюся память, но интересует почему занято так много памяти и свопа в момент перед падением. Хотя если просуммировать колонку RSIZE - не получится 1.5 гигабайта.


В RSIZE не включён свап, зато включена shared память. Занято у тебя 987.5 - 54.7 - 87.0 - 0.7 - 10.4 - 39.4 = 795.3, из них 639.6 одна ява

redgremlin ★★★★★
()

Вот этот скрипт покажет потребление swap по процессам:

http://northernmost.org/blog/find-out-what-is-using-your-swap/

если сумма в выводе этого скрипта не 500 Мбайт, значит в swap скушан не процессами, а чем-то другим, допустим, tmpfs.

А сумма RSS, вроде как, должна примерно совпадать с объёмом занятой ОЗУ (987.5-54.7-87.0-10.4-39.4=796).

mky ★★★★★
()
Последнее исправление: mky (всего исправлений: 1)
Ответ на: комментарий от mky

Там постгрес, который активно shared использует. Поэтому сумма будет больше.

redgremlin ★★★★★
()
Ответ на: комментарий от mky

Померял потребление свопа скриптом - все совпадает с atop. Нашел два процесса которые его интесивно используют java и mongodb.

А сумма RSS, вроде как, должна примерно совпадать с объёмом занятой ОЗУ (987.5-54.7-87.0-10.4-39.4=796).

Выходит на момент включения OOM Killer у меня было свободно порядка 200 Мб. Странно тогда почему он включился(падение случается после запуска 4-х дополнительных процессов nodejs, которые в сумме занимают порядка 50 Мб памяти).

recon88
() автор топика
Ответ на: комментарий от recon88

Выходит на момент включения OOM Killer у меня было свободно порядка 200 Мб.

Нет. slab — это память взятая ядром (модулями) и она не свободная. Так же не факт, что cached-память, можеть быть освобождена, в ней живёт tmpfs (если используется) и память, выделенная под tmpfs может перетечь только в swap. buffers тоже часто не могут освобождены. Поэтому можно считать, что гарантированно у вас есть 54.7 Мбайт.

Можете попробовать сделать:

sync; echo 3 > /proc/sys/vm/drop_caches; cat /proc/meminfo

чтобы посмотреть, до каких значений у вас может снизится cached и buffers и по этим значениям оценивать объём свободной памяти.

Я бы советовал добавить ещё пару Гбайт swap'а (можно в файл с более низким приоритетом), и сделать:

echo 2 > /proc/sys/vm/overcommit_memory; echo 90 > /proc/sys/vm/overcommit_ratio

mky ★★★★★
()
Ответ на: комментарий от recon88

падение случается после запуска 4-х дополнительных процессов nodejs, которые в сумме занимают порядка 50 Мб памяти

Не забываем про фрагментацию памяти. Если каждому процессу требуется по 12Мб непрерывной памяти, далеко не факт, что в 54Мб свободной памяти их можно найти, там вполне может быть по 100 кусков по 0.5Мб в каждом. Даже с учётом того, что часть кэша можно освободить - вряд ли это будут непрерывные куски.

redgremlin ★★★★★
()
Ответ на: комментарий от redgremlin

А не пофигу ли это в user-mode?
AFAIK malloc() не выделяет _физически_ непрерывную память, непрерывной она делается только виртуально, на уровне страничного механизма.

bigbit ★★★★★
()
Ответ на: комментарий от mky

sync; echo 3 > /proc/sys/vm/drop_caches; cat /proc/meminfo

Действительно. Освободило не достаточно памяти для запуска ноды, порядка 50 Мб осталось в кеше.

echo 2 > /proc/sys/vm/overcommit_memory; echo 90 > /proc/sys/vm/overcommit_ratio

такое к сожалению не могу сделать. Т.к. монга не будет работать в этом случае(она мапит всю базу в память, в результате чего имеем VSIZE порядка 7 Gb).

По поводу потребления: проанализировал лог OOM Killer на предмет потребления и нашел следующее:

 pid    uid  tgid total_vm      rss nr_ptes swapents oom_score_adj name
31968   106 31968  2072041    10442     684    84829             0 mongod
29088  1000 28966   240279   159652     437    42436             0 java

Если я правильно понимаю, то для процесса можно вычислить потребление памяти по формуле : (rss + swapents) * page_size. Тогда получаются интересные результаты: java занимает как положено, порядка 800 Мб, а монга - неожиданные 372 Мб. После запуска потребление монги находится в пределах 50-70 Мб(RSS + swap из вашего скрипта). Так что если формула правильная, то скорее всего причина в утечках в монге, и решением будет её периодический перезапуск.

recon88
() автор топика
Ответ на: комментарий от recon88

для процесса можно вычислить потребление памяти по формуле : (rss + swapents) * page_size

Вроде как ещё нужно добавить nr_ptes — объём памяти занятой таблицей страничного преобразования: (rss + swapents + nr_ptes) * page_size

Относительно того, что virt там под 8 Гбайт, нужно смотреть, как мапится файл в память. Если там просто mmap (MAP_SHARED), то объём этого файла не будет учтён при вычислении overcommit_memory. Совет поставить 2 в overcommit_memory я взял из гугла, сам с монгой не работал, так что вам виднее. Если mongodb была выделена память (alloc()), то она считает себя в праве использовать весь выделенный объём. И в этом вся проблема overcommit, что процесс может быть «убит» (SIGKILL) без вариантов обработки ошибки и «плавного» завершения работы.

то скорее всего причина в утечках в монге

Тут я ничего не подскажу. Вобще не знаю, сколько памяти может занять сама монга. Вроде как в faq пишется, что основной размер её памти это mmap файла с БД, но mmap-файл не должен залазить в swap. Может там висят какие не закрытые транзакции... Может кто что подскажет в отдельной теме.

mky ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.