add print_proc_table, add min_mem_report_interval

This commit is contained in:
Alexey Avramov 2019-02-17 04:51:53 +09:00
parent 3b5eafdaeb
commit 62f4948b39

127
nohang
View File

@ -76,12 +76,14 @@ psi_path = '/proc/pressure/memory'
psi_support = os.path.exists(psi_path)
HR = '~' * 79
HR = ''
# todo: make config option
print_total_stat = True
debug = False
print_proc_table = False
min_mem_report_interval = 10
##########################################################################
@ -133,7 +135,7 @@ def update_stat_dict_and_print(key):
if print_total_stat:
stats_msg = '{}\n\033[4mThe following corrective actions have been implemented in the last {}:\033[0m'.format(
stats_msg = '{}\n\033[4mWhat happened in the last {}:\033[0m'.format(
HR, format_time(time() - start_time))
for i in stat_dict:
@ -153,7 +155,7 @@ def psi_mem_some_avg10():
def check_mem():
"""find mem_available"""
return int(rline1('/proc/meminfo').split(':')[1].strip(' kB\n'))
return int(rline1('/proc/meminfo').split(':')[1][:-4])
def check_mem_and_swap():
@ -161,13 +163,13 @@ def check_mem_and_swap():
with open('/proc/meminfo') as f:
for n, line in enumerate(f):
if n is 2:
mem_available = int(line.split(':')[1].strip(' kB\n'))
mem_available = int(line.split(':')[1][:-4])
continue
if n is swap_total_index:
swap_total = int(line.split(':')[1].strip(' kB\n'))
swap_total = int(line.split(':')[1][:-4])
continue
if n is swap_free_index:
swap_free = int(line.split(':')[1].strip(' kB\n'))
swap_free = int(line.split(':')[1][:-4])
break
return mem_available, swap_total, swap_free
@ -359,7 +361,6 @@ def pid_to_cmdline(pid):
return f.read().replace('\x00', ' ').rstrip()
def pid_to_uid(pid):
'''return euid'''
try:
@ -373,9 +374,6 @@ def pid_to_uid(pid):
return f_list[uid_index].split('\t')[2]
def notify_send_wait(title, body):
'''GUI notifications with UID != 0'''
with Popen(['notify-send', '--icon=dialog-warning', title, body]) as proc:
@ -399,9 +397,6 @@ def notify_helper(title, body):
title, body))
def send_notify_warn():
"""
Look for process with maximum 'badness' and warn user with notification.
@ -431,11 +426,6 @@ def send_notify_warn():
title = 'Low memory'
'''
'''
body = 'Next victim: {}[{}]'.format(
name.replace(
@ -460,7 +450,6 @@ def send_notify_warn():
notify_send_wait(title, body)
'''
b = """{} 'Low memory' 'MemAvail: {}%\nSwapFree: {}%' &""".format(
notify_helper_path,
round(mem_available / mem_total * 100),
@ -473,9 +462,6 @@ def send_notify_warn():
print('t:', t1 - t0)
def send_notify(signal, name, pid):
"""
Notificate about OOM Preventing.
@ -569,6 +555,8 @@ def fattest():
-> find_mem_hog() or find_victim() or find_worst_process()
"""
ft1 = time()
pid_list = get_pid_list()
pid_list.remove(self_pid)
@ -584,14 +572,13 @@ def fattest():
pid_badness_list = []
if debug:
if print_proc_table:
print(' PID badness Name eUID')
print('------- ------- --------------- ----------')
for pid in pid_list:
# find and modify badness (if it needs)
try:
@ -620,9 +607,7 @@ def fattest():
if search(re_tup[1], uid) is not None:
badness += int(re_tup[0])
if debug:
if print_proc_table:
print('{} {} {} {}'.format(
pid.rjust(7),
str(badness).rjust(7),
@ -631,8 +616,6 @@ def fattest():
)
)
except FileNotFoundError:
continue
except ProcessLookupError:
@ -652,11 +635,18 @@ def fattest():
# Get maximum 'badness' value
victim_badness = pid_tuple_list[1]
print(
'\nWorst process (PID: {}, Name: {}, badness: {}) found in {} ms'.format(
pid,
pid_to_name(pid),
victim_badness,
round((time() - ft1) * 1000)
)
)
return pid, victim_badness
def find_victim_and_send_signal(signal):
"""
Find victim with highest badness and send SIGTERM/SIGKILL
@ -925,7 +915,7 @@ def find_victim_and_send_signal(signal):
preventing_oom_message = '{}' \
'\n\033[4mImplement a corrective action:\033[0m\n ' \
'Sending \033[4m{}\033[0m to the victim; {}'.format(
'Send \033[4m{}\033[0m to the victim; {}'.format(
victim_info, sig_dict[signal], send_result)
key = 'Send \033[35m{}\033[0m to \033[35m{}\033[0m'.format(
@ -938,12 +928,12 @@ def find_victim_and_send_signal(signal):
response_time = time() - time0
send_result = 'no such process; response time: {} ms'.format(
round(response_time * 1000))
key = 'The victim died in the search process: FileNotFoundError'
key = '\033[33mFileNotFoundError\033[0m (the victim died in the search process): '
except ProcessLookupError:
response_time = time() - time0
send_result = 'no such process; response time: {} ms'.format(
round(response_time * 1000))
key = 'The victim died in the search process: ProcessLookupError'
key = '\033[33mProcessLookupError\033[0m (the victim died in the search process): '
print(mem_info)
print(preventing_oom_message)
@ -1087,7 +1077,7 @@ def calculate_percent(arg_key):
##########################################################################
# Lock all memory
# Try to lock all memory
mlockall()
@ -1113,7 +1103,7 @@ if mem_list_names[2] != 'MemAvailable':
swap_total_index = mem_list_names.index('SwapTotal')
swap_free_index = swap_total_index + 1
mem_total = int(mem_list[0].split(':')[1].strip(' kB\n'))
mem_total = int(mem_list[0].split(':')[1][:-4])
# Get names from /proc/*/status to be able to get VmRSS and VmSwap values
@ -1601,6 +1591,7 @@ if gui_notifications or gui_low_memory_warnings:
notify_sig_dict = {SIGKILL: 'Killing',
SIGTERM: 'Terminating'}
rate_mem = rate_mem * 1048576
rate_swap = rate_swap * 1048576
rate_zram = rate_zram * 1048576
@ -1613,7 +1604,7 @@ warn_time_now = 0
warn_time_delta = 1000
warn_timer = 0
if debug:
if print_proc_table:
print()
fattest()
print()
@ -1636,6 +1627,14 @@ if psi_support and not ignore_psi:
avg_value = ''
if print_mem_check_results:
# to find delta mem
wt2 = 0
new_mem = 0
# init mem report interval
report0 = 0
while True:
@ -1662,6 +1661,7 @@ while True:
mem_available, swap_total, swap_free = check_mem_and_swap()
# print(mem_available, swap_total, swap_free)
# если метры - получаем киб выше и сразу. см.
@ -1683,34 +1683,69 @@ while True:
if print_mem_check_results:
wt1 = time()
delta = (mem_available + swap_free) - new_mem
t_cycle = wt1 - wt2
report_delta = wt1 - report0
if report_delta >= min_mem_report_interval:
mem_report = True
new_mem = mem_available + swap_free
report0 = wt1
else:
mem_report = False
wt2 = time()
if mem_report:
speed = delta / 1024.0 / report_delta
speed_info = ' | ΔMem, M/s: {}'.format(
str(round(speed)).rjust(5)
)
# Calculate 'swap-column' width
swap_len = len(str(round(swap_total / 1024.0)))
# Output avialable mem sizes
if swap_total == 0 and mem_used_zram == 0:
print('{}MemAvail: {} M, {} %'.format(
print('{}MemAvail: {} M, {} %{}'.format(
avg_value,
human(mem_available, mem_len),
just_percent_mem(mem_available / mem_total)))
just_percent_mem(mem_available / mem_total),
speed_info
)
)
elif swap_total > 0 and mem_used_zram == 0:
print('{}MemAvail: {} M, {} % | SwapFree: {} M, {} %'.format(
print('{}MemAvail: {} M, {} % | SwapFree: {} M, {} %{}'.format(
avg_value,
human(mem_available, mem_len),
just_percent_mem(mem_available / mem_total),
human(swap_free, swap_len),
just_percent_swap(swap_free / (swap_total + 0.1))))
just_percent_swap(swap_free / (swap_total + 0.1)),
speed_info)
)
else:
print('{}MemAvail: {} M, {} % | SwapFree: {} M, {} % | Mem'
'UsedZram: {} M, {} %'.format(
'UsedZram: {} M, {} %{}'.format(
avg_value,
human(mem_available, mem_len),
just_percent_mem(mem_available / mem_total),
human(swap_free, swap_len),
just_percent_swap(swap_free / (swap_total + 0.1)),
human(mem_used_zram, mem_len),
just_percent_mem(mem_used_zram / mem_total)))
just_percent_mem(mem_used_zram / mem_total),
speed_info
)
)
# если swap_min_sigkill задан в абсолютной величине и Swap_total = 0
if swap_total > swap_min_sigkill_kb: # If swap_min_sigkill is absolute
@ -1813,8 +1848,11 @@ while True:
percent(zram_max_sigterm_kb / mem_total))
find_victim_and_send_signal(SIGTERM)
# сделать одно время для обоих уровней.
kill_psi_t0 = time()
term_psi_t0 = time()
# -> psi_t0
# LOW MEMORY WARNINGS
elif gui_low_memory_warnings:
@ -1835,4 +1873,5 @@ while True:
# SLEEP BETWEEN MEM CHECKS
else:
sleep_after_check_mem()