diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-04-09 23:21:15 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-04-09 23:21:15 +0000 |
commit | a982a5158e27c500687ede58f3ee6333e71df89c (patch) | |
tree | b6bd4553762d2206860912465e7a7b591b631912 | |
parent | c234953ea553e5e413671d95e45192fafb8ddaf0 (diff) | |
parent | 20de82dde24f5097d777b7a2681623b06a6f5206 (diff) | |
download | lmkd-a982a5158e27c500687ede58f3ee6333e71df89c.tar.gz |
Snap for 11692525 from 20de82dde24f5097d777b7a2681623b06a6f5206 to sdk-release
Change-Id: I710be0deec8a54ab58256eb88fca04ed4901d31f
-rw-r--r-- | README.md | 5 | ||||
-rw-r--r-- | lmkd.cpp | 81 | ||||
-rw-r--r-- | lmkd.rc | 3 |
3 files changed, 67 insertions, 22 deletions
@@ -95,6 +95,11 @@ properties: - `ro.lmk.direct_reclaim_threshold_ms`: direct reclaim duration threshold in milliseconds to consider the system as stuck in direct reclaim. Default = 0 (disabled) + - `ro.lmk.swap_compression_ratio`: swap average compression ratio to be used when + estimating how much data can be swapped. Setting it + to 0 will ignore available memory and assume that + configured swap size can be always utilized fully. + Default = 1 (no compression). lmkd will set the following Android properties according to current system configurations: @@ -162,6 +162,8 @@ static inline void trace_kill_end() {} #define DEF_COMPLETE_STALL 700 /* ro.lmk.direct_reclaim_threshold_ms property defaults */ #define DEF_DIRECT_RECL_THRESH_MS 0 +/* ro.lmk.swap_compression_ratio property defaults */ +#define DEF_SWAP_COMP_RATIO 1 #define LMKD_REINIT_PROP "lmkd.reinit" @@ -195,9 +197,10 @@ struct psi_threshold { int threshold_ms; }; -/* Listener for direct reclaim state changes */ +/* Listener for direct reclaim and kswapd state changes */ static std::unique_ptr<android::bpf::memevents::MemEventListener> memevent_listener(nullptr); static struct timespec direct_reclaim_start_tm; +static struct timespec kswapd_start_tm; static int level_oomadj[VMPRESS_LEVEL_COUNT]; static int mpevfd[VMPRESS_LEVEL_COUNT] = { -1, -1, -1 }; @@ -231,6 +234,7 @@ static bool use_psi_monitors = false; static int kpoll_fd; static bool delay_monitors_until_boot; static int direct_reclaim_threshold_ms; +static int swap_compression_ratio; static struct psi_threshold psi_thresholds[VMPRESS_LEVEL_COUNT] = { { PSI_SOME, 70 }, /* 70ms out of 1sec for partial stall */ { PSI_SOME, 100 }, /* 100ms out of 1sec for partial stall */ @@ -1591,9 +1595,9 @@ static void ctrl_command_handler(int dsock_idx) { * waiting, during boot-up, for BPF programs to be loaded. */ if (init_memevent_listener_monitoring()) { - ALOGI("Using memevents for direct reclaim detection"); + ALOGI("Using memevents for direct reclaim and kswapd detection"); } else { - ALOGI("Using vmstats for direct reclaim detection"); + ALOGI("Using vmstats for direct reclaim and kswapd detection"); if (direct_reclaim_threshold_ms > 0) { ALOGW("Kernel support for direct_reclaim_threshold_ms is not found"); direct_reclaim_threshold_ms = 0; @@ -1945,8 +1949,12 @@ static int meminfo_parse(union meminfo *mi) { // 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. +// Swap compression ratio in the calculation can be adjusted using swap_compression_ratio tunable. +// By setting swap_compression_ratio to 0, available memory can be ignored. static inline int64_t get_free_swap(union meminfo *mi) { - return std::min(mi->field.free_swap, mi->field.easy_available); + if (swap_compression_ratio) + return std::min(mi->field.free_swap, mi->field.easy_available * swap_compression_ratio); + return mi->field.free_swap; } /* /proc/vmstat parsing routines */ @@ -2673,6 +2681,7 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ bool critical_stall = false; bool in_direct_reclaim; long direct_reclaim_duration_ms; + bool in_kswapd_reclaim; if (clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm) != 0) { ALOGE("Failed to get current time"); @@ -2725,9 +2734,15 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ swap_low_threshold = 0; } - in_direct_reclaim = memevent_listener ? (direct_reclaim_start_tm.tv_sec != 0 || - direct_reclaim_start_tm.tv_nsec != 0) - : (vs.field.pgscan_direct != init_pgscan_direct); + if (memevent_listener) { + in_direct_reclaim = + direct_reclaim_start_tm.tv_sec != 0 || direct_reclaim_start_tm.tv_nsec != 0; + in_kswapd_reclaim = kswapd_start_tm.tv_sec != 0 || kswapd_start_tm.tv_nsec != 0; + } else { + in_direct_reclaim = vs.field.pgscan_direct != init_pgscan_direct; + in_kswapd_reclaim = (vs.field.pgscan_kswapd != init_pgscan_kswapd) || + (vs.field.pgrefill != init_pgrefill); + } /* Identify reclaim state */ if (in_direct_reclaim) { @@ -2736,13 +2751,10 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ init_pgrefill = vs.field.pgrefill; direct_reclaim_duration_ms = get_time_diff_ms(&direct_reclaim_start_tm, &curr_tm); reclaim = DIRECT_RECLAIM; - } else if (vs.field.pgscan_kswapd != init_pgscan_kswapd) { + } else if (in_kswapd_reclaim) { init_pgscan_kswapd = vs.field.pgscan_kswapd; init_pgrefill = vs.field.pgrefill; reclaim = KSWAPD_RECLAIM; - } else if (vs.field.pgrefill != init_pgrefill) { - init_pgrefill = vs.field.pgrefill; - 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 @@ -2795,6 +2807,7 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ max_thrashing = thrashing; } +update_watermarks: /* * Refresh watermarks once per min in case user updated one of the margins. * TODO: b/140521024 replace this periodic update with an API for AMS to notify LMKD @@ -2930,6 +2943,14 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ .thrashing = (int)thrashing, .max_thrashing = max_thrashing, }; + static bool first_kill = true; + + /* Make sure watermarks are correct before the first kill */ + if (first_kill) { + first_kill = false; + watermarks.high_wmark = 0; // force recomputation + goto update_watermarks; + } /* Allow killing perceptible apps if the system is stalled */ if (critical_stall) { @@ -3315,17 +3336,25 @@ static void memevent_listener_notification(int data __unused, uint32_t events __ return; } - /* - * `mem_events` is ordered from oldest to newest, therefore we use - * the last/latest direct reclaim event as the current direct reclaim - * state. - */ - for (const mem_event_t mem_event : mem_events) { - if (mem_event.type == MEM_EVENT_DIRECT_RECLAIM_BEGIN) { - direct_reclaim_start_tm = curr_tm; - } else if (mem_event.type == MEM_EVENT_DIRECT_RECLAIM_END) { - direct_reclaim_start_tm.tv_sec = 0; - direct_reclaim_start_tm.tv_nsec = 0; + for (const mem_event_t& mem_event : mem_events) { + switch (mem_event.type) { + /* Direct Reclaim */ + case MEM_EVENT_DIRECT_RECLAIM_BEGIN: + direct_reclaim_start_tm = curr_tm; + break; + case MEM_EVENT_DIRECT_RECLAIM_END: + direct_reclaim_start_tm.tv_sec = 0; + direct_reclaim_start_tm.tv_nsec = 0; + break; + + /* kswapd */ + case MEM_EVENT_KSWAPD_WAKE: + kswapd_start_tm = curr_tm; + break; + case MEM_EVENT_KSWAPD_SLEEP: + kswapd_start_tm.tv_sec = 0; + kswapd_start_tm.tv_nsec = 0; + break; } } } @@ -3353,6 +3382,12 @@ static bool init_memevent_listener_monitoring() { memevent_listener.reset(); return false; } + if (!memevent_listener->registerEvent(MEM_EVENT_KSWAPD_WAKE) || + !memevent_listener->registerEvent(MEM_EVENT_KSWAPD_SLEEP)) { + ALOGE("Failed to register kswapd memevents"); + memevent_listener.reset(); + return false; + } int memevent_listener_fd = memevent_listener->getRingBufferFd(); if (memevent_listener_fd < 0) { @@ -3979,6 +4014,8 @@ static bool update_props() { delay_monitors_until_boot = GET_LMK_PROPERTY(bool, "delay_monitors_until_boot", false); direct_reclaim_threshold_ms = GET_LMK_PROPERTY(int64, "direct_reclaim_threshold_ms", DEF_DIRECT_RECL_THRESH_MS); + swap_compression_ratio = + GET_LMK_PROPERTY(int64, "swap_compression_ratio", DEF_SWAP_COMP_RATIO); reaper.enable_debug(debug_process_killing); @@ -55,3 +55,6 @@ on property:persist.device_config.lmkd_native.filecache_min_kb=* on property:persist.device_config.lmkd_native.direct_reclaim_threshold_ms=* setprop lmkd.reinit ${sys.boot_completed:-0} + +on property:persist.device_config.lmkd_native.swap_compression_ratio=* + setprop lmkd.reinit ${sys.boot_completed:-0} |