lmkd: measure free swap as available and easily reclaimable memory
In the case of ZRAM, SwapFree does not represent the actual free swap amount because swap space is taken from the free memory or reclaimed. Therefore use free memory and easily reclaimable memory as an approximation of how much free swap system can use. Use SwapFree as a measure of how much swap space the system will consider using. Min of those two measurements is used to decide how much usable swap the system still has. Bug: 238495258 Signed-off-by: Suren Baghdasaryan <surenb@google.com> Change-Id: Ia7b0cc4a744d14c0d6e52603795917cf5824ea15
This commit is contained in:
parent
ba9ea6e3d6
commit
495db5c643
22
lmkd.cpp
22
lmkd.cpp
|
|
@ -450,6 +450,7 @@ union meminfo {
|
|||
/* fields below are calculated rather than read from the file */
|
||||
int64_t nr_file_pages;
|
||||
int64_t total_gpu_kb;
|
||||
int64_t easy_available;
|
||||
} field;
|
||||
int64_t arr[MI_FIELD_COUNT];
|
||||
};
|
||||
|
|
@ -1876,10 +1877,19 @@ static int meminfo_parse(union meminfo *mi) {
|
|||
mi->field.nr_file_pages = mi->field.cached + mi->field.swap_cached +
|
||||
mi->field.buffers;
|
||||
mi->field.total_gpu_kb = read_gpu_total_kb();
|
||||
mi->field.easy_available = mi->field.nr_free_pages + mi->field.inactive_file;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// In the case of ZRAM, mi->field.free_swap can't be used directly because swap space is taken
|
||||
// from the free memory or reclaimed. Use the lowest of free_swap and easily available memory to
|
||||
// measure free swap because they represent how much swap space the system will consider to use
|
||||
// and how much it can actually use.
|
||||
static inline int64_t get_free_swap(union meminfo *mi) {
|
||||
return std::min(mi->field.free_swap, mi->field.easy_available);
|
||||
}
|
||||
|
||||
/* /proc/vmstat parsing routines */
|
||||
static bool vmstat_parse_line(char *line, union vmstat *vs) {
|
||||
char *cp;
|
||||
|
|
@ -2388,7 +2398,7 @@ static int kill_one_process(struct proc* procp, int min_oom_score, struct kill_i
|
|||
kill_st.oom_score = procp->oomadj;
|
||||
kill_st.min_oom_score = min_oom_score;
|
||||
kill_st.free_mem_kb = mi->field.nr_free_pages * page_k;
|
||||
kill_st.free_swap_kb = mi->field.free_swap * page_k;
|
||||
kill_st.free_swap_kb = get_free_swap(mi) * page_k;
|
||||
stats_write_lmk_kill_occurred(&kill_st, mem_st);
|
||||
|
||||
ctrl_data_write_lmk_kill_occurred((pid_t)pid, uid);
|
||||
|
|
@ -2564,7 +2574,7 @@ void calc_zone_watermarks(struct zoneinfo *zi, struct zone_watermarks *watermark
|
|||
}
|
||||
|
||||
static int calc_swap_utilization(union meminfo *mi) {
|
||||
int64_t swap_used = mi->field.total_swap - mi->field.free_swap;
|
||||
int64_t swap_used = mi->field.total_swap - get_free_swap(mi);
|
||||
int64_t total_swappable = mi->field.active_anon + mi->field.inactive_anon +
|
||||
mi->field.shmem + swap_used;
|
||||
return total_swappable > 0 ? (swap_used * 100) / total_swappable : 0;
|
||||
|
|
@ -2657,7 +2667,7 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_
|
|||
/* Check free swap levels */
|
||||
if (swap_free_low_percentage) {
|
||||
swap_low_threshold = mi.field.total_swap * swap_free_low_percentage / 100;
|
||||
swap_is_low = mi.field.free_swap < swap_low_threshold;
|
||||
swap_is_low = get_free_swap(&mi) < swap_low_threshold;
|
||||
} else {
|
||||
swap_low_threshold = 0;
|
||||
}
|
||||
|
|
@ -2770,7 +2780,7 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_
|
|||
kill_reason = LOW_SWAP_AND_THRASHING;
|
||||
snprintf(kill_desc, sizeof(kill_desc), "device is low on swap (%" PRId64
|
||||
"kB < %" PRId64 "kB) and thrashing (%" PRId64 "%%)",
|
||||
mi.field.free_swap * page_k, swap_low_threshold * page_k, thrashing);
|
||||
get_free_swap(&mi) * page_k, swap_low_threshold * page_k, thrashing);
|
||||
/* Do not kill perceptible apps unless below min watermark or heavily thrashing */
|
||||
if (wmark > WMARK_MIN && thrashing < thrashing_critical_pct) {
|
||||
min_score_adj = PERCEPTIBLE_APP_ADJ + 1;
|
||||
|
|
@ -2781,7 +2791,7 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_
|
|||
kill_reason = LOW_MEM_AND_SWAP;
|
||||
snprintf(kill_desc, sizeof(kill_desc), "%s watermark is breached and swap is low (%"
|
||||
PRId64 "kB < %" PRId64 "kB)", wmark < WMARK_LOW ? "min" : "low",
|
||||
mi.field.free_swap * page_k, swap_low_threshold * page_k);
|
||||
get_free_swap(&mi) * page_k, swap_low_threshold * page_k);
|
||||
/* Do not kill perceptible apps unless below min watermark or heavily thrashing */
|
||||
if (wmark > WMARK_MIN && thrashing < thrashing_critical_pct) {
|
||||
min_score_adj = PERCEPTIBLE_APP_ADJ + 1;
|
||||
|
|
@ -3060,7 +3070,7 @@ static void mp_event_common(int data, uint32_t events, struct polling_params *po
|
|||
|
||||
// If we still have enough swap space available, check if we want to
|
||||
// ignore/downgrade pressure events.
|
||||
if (mi.field.free_swap >=
|
||||
if (get_free_swap(&mi) >=
|
||||
mi.field.total_swap * swap_free_low_percentage / 100) {
|
||||
// If the pressure is larger than downgrade_pressure lmk will not
|
||||
// kill any process, since enough memory is available.
|
||||
|
|
|
|||
Loading…
Reference in New Issue