diff --git a/lmkd.cpp b/lmkd.cpp index 0afcf2f..f3c301e 100644 --- a/lmkd.cpp +++ b/lmkd.cpp @@ -201,6 +201,7 @@ static int thrashing_limit_pct; static int thrashing_limit_decay_pct; static int thrashing_critical_pct; static int swap_util_max; +static int64_t filecache_min_kb; static bool use_psi_monitors = false; static int kpoll_fd; static struct psi_threshold psi_thresholds[VMPRESS_LEVEL_COUNT] = { @@ -2397,6 +2398,7 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ static struct wakeup_info wi; static struct timespec thrashing_reset_tm; static int64_t prev_thrash_growth = 0; + static bool check_filecache = false; union meminfo mi; union vmstat vs; @@ -2475,7 +2477,10 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ init_pgscan_kswapd = vs.field.pgscan_kswapd; reclaim = KSWAPD_RECLAIM; } else if (workingset_refault_file == prev_workingset_refault) { - /* Device is not thrashing and not reclaiming, bail out early until we see these stats changing*/ + /* + * Device is not thrashing and not reclaiming, bail out early until we see these stats + * changing + */ goto no_kill; } @@ -2488,7 +2493,7 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ * important for a slow growing refault case. While retrying, we should keep * monitoring new thrashing counter as someone could release the memory to mitigate * the thrashing. Thus, when thrashing reset window comes, we decay the prev thrashing - * counter by window counts. if the counter is still greater than thrashing limit, + * counter by window counts. If the counter is still greater than thrashing limit, * we preserve the current prev_thrash counter so we will retry kill again. Otherwise, * we reset the prev_thrash counter so we will stop retrying. */ @@ -2570,6 +2575,7 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ if (wmark > WMARK_MIN && thrashing < thrashing_critical_pct) { min_score_adj = PERCEPTIBLE_APP_ADJ + 1; } + check_filecache = true; } else if (swap_is_low && wmark < WMARK_HIGH) { /* Both free memory and swap are low */ kill_reason = LOW_MEM_AND_SWAP; @@ -2600,6 +2606,7 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ if (thrashing < thrashing_critical_pct) { min_score_adj = PERCEPTIBLE_APP_ADJ + 1; } + check_filecache = true; } else if (reclaim == DIRECT_RECLAIM && thrashing > thrashing_limit) { /* Page cache is thrashing while in direct reclaim (mostly happens on lowram devices) */ kill_reason = DIRECT_RECL_AND_THRASHING; @@ -2610,6 +2617,21 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ if (thrashing < thrashing_critical_pct) { min_score_adj = PERCEPTIBLE_APP_ADJ + 1; } + check_filecache = true; + } else if (check_filecache) { + int64_t file_lru_kb = (vs.field.nr_inactive_file + vs.field.nr_active_file) * page_k; + + if (file_lru_kb < filecache_min_kb) { + /* File cache is too low after thrashing, keep killing background processes */ + kill_reason = LOW_FILECACHE_AFTER_THRASHING; + snprintf(kill_desc, sizeof(kill_desc), + "filecache is low (%" PRId64 "kB < %" PRId64 "kB) after thrashing", + file_lru_kb, filecache_min_kb); + min_score_adj = PERCEPTIBLE_APP_ADJ + 1; + } else { + /* File cache is big enough, stop checking */ + check_filecache = false; + } } /* Kill a process if necessary */ @@ -3409,6 +3431,7 @@ static void update_props() { thrashing_critical_pct = max(0, property_get_int32("ro.lmk.thrashing_limit_critical", thrashing_limit_pct * 2)); swap_util_max = clamp(0, 100, property_get_int32("ro.lmk.swap_util_max", 100)); + filecache_min_kb = property_get_int64("ro.lmk.filecache_min_kb", 0); } int main(int argc, char **argv) { diff --git a/statslog.h b/statslog.h index e0859fa..44af35f 100644 --- a/statslog.h +++ b/statslog.h @@ -63,6 +63,7 @@ enum kill_reasons { LOW_MEM_AND_THRASHING, DIRECT_RECL_AND_THRASHING, LOW_MEM_AND_SWAP_UTIL, + LOW_FILECACHE_AFTER_THRASHING, KILL_REASON_COUNT };