Парадоксально, но факт, в *nix'овом мире всякие мониторилки очень популярны еще и потому, что средства предоставляемые системой, легко ответить на вопрос "все плохо или все хорошо?" не позволяют, а требуют дополнительной работы мозга. Например, в самых дружелюбных *nix'ах статистика по памяти в системном мониторе выглядит вот так:
Не говоря уже о том что этот самый системный монитор может рассказать про память используемую процессом:
Без дополнительных знаний догадаться что это, с чем его едят, и насколько плохи или хороши показания приборов, несколько проблематично. Поэтому используют всякие мониторилки памяти, которые хоть могут сказать сколько памяти еще есть на свободе, надеясь что люди которые делали эти мониторилки, таки понимают в этих всех видах использования памяти лучше чем ты:
Вы думали что понимают? А вот и фиг там. Из самой дружелюбной системы, переносимся в самую открытую(ирония). В Linux видами колбасных обрезков, в которых следует соображать пользователю, не балуют:
$ free -m
total used free shared buffers cached
Mem: 2048 1820 228 0 174 1205
-/+ buffers/cache: 440 1607
Swap: 2086 0 2086
Правда конечно стоит помнить, что "по настоящему used" и "по настоящему free" находятся во второй строчке. Потому как память, еще доступная приложениям, это по-сути free + buffers + cached, ну и соответственно buffers и cached, хотя и used, но система их освободит, если будет нужно. Если эта арифметика еще не задолбала можно конечно добавить трешачка, и посмотреть в /proc/meminfo
$ cat /proc/meminfo
MemTotal: 2097152 kB
MemFree: 233448 kB
Buffers: 178372 kB
Cached: 1234100 kB
SwapCached: 20 kB
Active: 957732 kB
Inactive: 611532 kB
HighTotal: 0 kB
HighFree: 0 kB
LowTotal: 2097152 kB
LowFree: 233448 kB
SwapTotal: 2136636 kB
SwapFree: 2136592 kB
Dirty: 460 kB
Writeback: 0 kB
AnonPages: 150672 kB
Mapped: 17888 kB
Slab: 214924 kB
PageTables: 4720 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
CommitLimit: 3185212 kB
Committed_AS: 301808 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 1292 kB
VmallocChunk: 34359737055 kB
В принципе первые четыре строки нам знакомы по выводу free, а остальные: тема для отдельной беседы. Как посчитать процент занятой памяти? - Например вот так:
awk '
BEGIN{total=0;free=0;buffers=0;cached=0}
/^MemTotal/{total=$2}
/^MemFree/{free=$2}
/^Buffers/{buffers=$2}
/^Cached/{cached = $2}
END{printf "%4.2f",(total - buffers - cached - free )/total*100}' /proc/meminfo
Для тех кто не знает awk: блок BEGIN выполняется вначале работы, блок END - в конце, остальные - на каждой строчке файла. В нашем случае, на нужной строчке просто сохраняем соответствующие числа в переменные, и потом считаем. В принципе, ничего сложного. Каково же было мое удивление, когда xmobar начал выдавать отрицательные значения процента используемой памяти:
Причина как оказалась достаточно банальна. В новых Linux'ах в /proc/meminfo добавили еще одну строчку:
$ cat /proc/meminfo
MemTotal: 949328 kB
MemFree: 542568 kB
MemAvailable: 870912 kB
Buffers: 22636 kB
Cached: 321972 kB
SwapCached: 0 kB
Active: 216328 kB
Inactive: 163272 kB
Active(anon): 35100 kB
Inactive(anon): 448 kB
Active(file): 181228 kB
Inactive(file): 162824 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 102396 kB
SwapFree: 102396 kB
Dirty: 0 kB
Writeback: 0 kB
AnonPages: 35004 kB
Mapped: 36504 kB
Shmem: 560 kB
Slab: 15724 kB
SReclaimable: 9540 kB
SUnreclaim: 6184 kB
KernelStack: 1352 kB
PageTables: 1096 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 577060 kB
Committed_AS: 146536 kB
VmallocTotal: 1105920 kB
VmallocUsed: 4636 kB
VmallocChunk: 864076 kB
И что-то пошло не так. По-сути awk'шный скриптик который выше все еще работает как нужно:
$ awk 'BEGIN{total=0;free=0;buffers=0;cached=0} /^MemTotal/{total=$2} /^MemFree/{free=$2} /^Buffers/{buffers=$2} /^Cached/{cached = $2} END{printf "%4.2f\n",(total - buffers - cached - free )/total*100}' /proc/meminfo
6.59
хотя теперь можно и как-то так:
awk 'BEGIN{total=0;available=0} /^MemTotal/{total=$2} /^MemAvailable/{available=$2} END{printf "%4.2f",(total - available)/total*100}' /proc/meminfo
8.30
Разница в результатах небольшая, но есть, потому что
MemAvailable != MemFree + Buffers + Cached
fileMEM = readFile "/proc/meminfo"
parseMEM :: IO [Float]
parseMEM =
do file <- br="" filemem=""> let content = map words $ take 4 $ lines file
[total, free, buffer, cache] = map (\line -> (read $ line !! 1 :: Float) / 1024) content
rest = free + buffer + cache
used = total - rest
usedratio = used / total
return [usedratio, total, free, buffer, cache, rest, used]->
Переводя с непонятного: берем первые четыре строчки файла, предполагаем что на первой лежит total, на второй free, и так далее. Без всяких проверок. Знаете почему так? Потому что Haskell фигово связан с реальным миром(зато идеологически правильно), и поскольку язык скорее экспериментальный, красота кода, важнее практического результата и стабильности, тем более что стабильность частично обещается компилятором. В итоге трахаешься час шобы получить красивую строчку, и пофигу шо она делает только половину того шо должна. Конечно, в более поздних версиях автору пришлось потрахаться еще чуть-чуть:
fileMEM = readFile "/proc/meminfo"
parseMEM :: IO [Float]
parseMEM =
do file <- br="" filemem=""> let content = map words $ take 8 $ lines file
info = M.fromList $ map (\line -> (head line, (read $ line !! 1 :: Float) / 1024)) content
[total, free, buffer, cache] = map (info M.!) ["MemTotal:", "MemFree:", "Buffers:", "Cached:"]
available = M.findWithDefault (free + buffer + cache) "MemAvailable:" info
used = total - available
usedratio = used / total
freeratio = free / total
availableratio = available / total
return [usedratio, freeratio, availableratio, total, free, buffer, cache, available, used]->
Правда, более поздняя версия в Debian'е еще недоступна.
Комментариев нет:
Отправить комментарий