add i-memhog

This commit is contained in:
Alexey Avramov 2019-06-23 14:00:23 +09:00
parent e0dbf486d1
commit fc0eafa9be
4 changed files with 323 additions and 0 deletions

View File

@ -31,6 +31,7 @@
- [x] `oom-sort`
- [x] `psi-top`
- [x] `psi-monitor`
- [x] `i-memhog`
- [x] Improve poll rate algorithm
- [x] Fixed Makefile for installation on CentOS 7 (remove gzip `-k` option).
- [x] Added `max_post_sigterm_victim_lifetime` option: send SIGKILL to the victim if it doesn't respond to SIGTERM for a certain time
@ -42,6 +43,7 @@
- [x] Removed self-defense options from the config, use systemd unit scheduling instead
- [x] Added the ability to send any signal instead of SIGTERM for processes with certain names
- [x] Added initial support for `PSI`
- [x] Recheck memory levels after finding a victim
- [x] Improved user input validation
- [x] Improved documentation
- [x] Handle signals

View File

@ -12,6 +12,7 @@ install:
install -m0755 ./oom-sort $(DESTDIR)/$(PREFIX)/usr/bin/oom-sort
install -m0755 ./psi-top $(DESTDIR)/$(PREFIX)/usr/bin/psi-top
install -m0755 ./psi-monitor $(DESTDIR)/$(PREFIX)/usr/bin/psi-monitor
install -m0755 ./i-memhog $(DESTDIR)/$(PREFIX)/usr/bin/i-memhog
install -d $(DESTDIR)/$(PREFIX)/etc/nohang
-git describe --tags --long --dirty > ./version
@ -41,6 +42,7 @@ uninstall:
rm -fv $(PREFIX)/usr/bin/oom-sort
rm -fv $(PREFIX)/usr/bin/psi-top
rm -fv $(PREFIX)/usr/bin/psi-monitor
rm -fv $(PREFIX)/usr/bin/i-memhog
rm -fv $(PREFIX)/usr/share/man/man1/nohang.1.gz
rm -fv $(PREFIX)/usr/share/man/man1/oom-sort.1.gz
rm -fv $(PREFIX)/lib/systemd/system/nohang.service

View File

@ -533,6 +533,10 @@ some 0.29 7.58 14.58 | full 0.28 6.92 13.24
```
</details>
### i-memhog
`i-memhog` is an interactive memory hog for testing purposes.
## Contribution
Use cases, feature requests and any questions are [welcome](https://github.com/hakavlad/nohang/issues).

315
i-memhog Executable file
View File

@ -0,0 +1,315 @@
#!/usr/bin/env python3
from signal import signal, SIGTERM
from time import sleep
from sys import exit
import os
# чек общей доступной, для lim2avail
def total_mem_available():
with open('/proc/meminfo') as file:
mem_list = file.readlines()
mem_available = meminfo_num(mem_list, mem_available_index)
swap_free = meminfo_num(mem_list, swap_free_index)
return round((swap_free + mem_available) / 1024) # MiB
# добитие байтами рандома
def terminal():
ex = []
while True:
try:
ex.append(os.urandom(1))
except MemoryError:
continue
def meminfo_num(mem_list, index):
return int(mem_list[index].split(':')[1].split(' ')[-2])
# выдача основных показателей meminfo, KiB
def mem_check_main():
with open('/proc/meminfo') as file:
mem_list = file.readlines()
mem_available = meminfo_num(mem_list, mem_available_index)
swap_total = meminfo_num(mem_list, swap_total_index)
swap_free = meminfo_num(mem_list, swap_free_index)
return mem_available, swap_total, swap_free
def signal_handler(signum, frame):
print('Got signal {}'.format(signum))
# sleep(1)
# exit()
def meminfo():
# получаем сырой mem_list
with open('/proc/meminfo') as file:
mem_list = file.readlines()
# получаем список названий позиций: MemTotal etc
mem_list_names = []
for s in mem_list:
mem_list_names.append(s.split(':')[0])
# ищем MemAvailable, обрабатываем исключение
try:
mem_available_index = mem_list_names.index('MemAvailable')
except ValueError:
print("Your Linux kernel is too old (3.14+ requied), bye!")
# исключение для ядер < 3.14, не определяющих MemAvailable
exit()
# ищем позиции SwapTotl и SwapFree
swap_total_index = mem_list_names.index('SwapTotal')
swap_free_index = mem_list_names.index('SwapFree')
buffers_index = mem_list_names.index('Buffers')
cached_index = mem_list_names.index('Cached')
active_index = mem_list_names.index('Active')
inactive_index = mem_list_names.index('Inactive')
shmem_index = mem_list_names.index('Shmem')
# ищем значение MemTotal в KiB
mem_total = int(mem_list[0].split(':')[1].split(' ')[-2])
return mem_total, mem_available_index, swap_total_index, swap_free_index, buffers_index, cached_index, active_index, inactive_index, shmem_index
meminfo_tuple = meminfo()
mem_total = meminfo_tuple[0]
mem_available_index = meminfo_tuple[1]
swap_total_index = meminfo_tuple[2]
swap_free_index = meminfo_tuple[3]
buffers_index = meminfo_tuple[4]
cached_index = meminfo_tuple[5]
active_index = meminfo_tuple[6]
inactive_index = meminfo_tuple[7]
shmem_index = meminfo_tuple[8]
# печать показателей на этапах работы
def print_mem():
mem_tup = mem_check_main()
mem_available = mem_tup[0]
swap_total = mem_tup[1]
swap_free = mem_tup[2]
print(
'MemAvailable: ',
round(
mem_available /
1024 /
1024,
3),
'GiB,',
round(
mem_available /
1024),
'MiB,',
round(
mem_available /
mem_total *
100,
1),
'%')
if swap_total != 0:
print(
'SwapFree: ',
round(
swap_free /
1024 /
1024,
3),
'GiB,',
round(
swap_free /
1024),
'MiB,',
round(
swap_free /
swap_total *
100,
1),
'%')
print('Total Free: ',
round((mem_available + swap_free) / 1024 / 1024,
3),
'GiB,',
round((mem_available + swap_free) / 1024),
'MiB,',
round((mem_available + swap_free) / (mem_total + swap_total) * 100,
1),
'%')
else:
print(
'Swap disabled'
)
# бесконечный жор
def inf():
print(
'Вводите целые неотрицательные числа. Чем больше, тем быстрее потребление памяти.\n1000 same обеспечивает потребление на уровне полтора гиг в секунду,\nurandom работает на скорости максимум 170 M/s'
)
same = input("same: ")
urandom = input("urandom: ")
expanding_list = []
print(
'Процесс неограниченного потребления пошёл... Press Ctrl + C for exit'
)
while True:
try:
expanding_list.append(os.urandom(int(urandom)))
expanding_list.append('#' * int(same))
except MemoryError:
print('MemoryError, start побайтовая добивалка!')
terminal()
def selfterm():
os.kill(os.getpid(), signal.SIGTERM)
# жор числп гиг
def lim():
expanding_list = []
n = input('На сколько гигабайт уменьшить доступную память?\n: ')
print('Погнали тратить ' + n + ' гиг...')
i = 0
while True:
i += 1
try:
expanding_list.append(os.urandom(int(100)))
expanding_list.append('#' * int(300))
except MemoryError:
print('MemoryError!')
break
if i > 2020202 * int(n):
print('DONE')
break
return expanding_list
# жор до остатка мегабайт
def lim2avail():
expanding_list = []
n = input(
'Сколько мегабайт общей доступной памяти (MemAvailable + SwapFree) оставить?\nВведите целое положительное число: '
)
# проверка на целое положительное
if n.isdigit():
n = int(n)
else:
print(
'Вы ввели не целое положительное число'
)
return 0
if n == 0:
print(
'Вы ввели не целое положительное число'
)
return 0
print(
'Погнали уменьшать доступную память до уровня ниже ' +
str(n) +
' MiB...')
while True:
try:
expanding_list.append(os.urandom(5000))
expanding_list.append('#' * 5000)
except MemoryError:
print('MemoryError!')
break
if total_mem_available() <= n:
print('DONE')
break
return expanding_list
print('WARNING: эта прога способна потратить память и повесить систему, будьте осторожны.')
print('При ее работе следите за показателями памяти.')
print('Ignore SIGTERM? (y|n)')
sss = input(': ')
if sss == 'y':
signal(SIGTERM, signal_handler)
print('The SIGTERM signal will be ignored')
else:
print('The SIGTERM signal will NOT be ignored')
ex_list = []
try:
while True:
print()
print_mem()
print()
print('Выберите вариант из списка ниже')
print('8 или i или I - запустить бесконечное потребление, предложив выбрать скорость потребления и энтропию')
print('7 или l или L - запустить ограниченное потребление заданного числа гигов')
print('6 или a или A - жрать память пока количество доступной памяти не опустится ниже заданного')
print('0 или с или С - очистить накопления при их наличии')
print('q или любой другой символ - выход (можно просто нажать Enter)')
li = input(': ')
if li is 'l' or li is 'L' or li is '7':
x = lim()
ex_list.append(x)
elif li is 'i' or li is 'I' or li is '8':
inf()
elif li is 'c' or li is 'C' or li is '0':
ex_list = []
x = 0
y = 0
elif li is '6' or li is 'a' or li is 'A':
y = lim2avail()
ex_list.append(y)
else:
exit()
except KeyboardInterrupt:
print()
print_mem()
selfterm()