Adding kswapd state monitoring with memevent_listener am: 6593e2cee6 am: 49fa9d895e

Original change: https://android-review.googlesource.com/c/platform/system/memory/lmkd/+/3025666

Change-Id: If644e45930a94618615e2c3aace72704ab06fe62
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Carlos Galo 2024-04-04 20:51:06 +00:00 committed by Automerger Merge Worker
commit 1221249fe9
1 changed files with 40 additions and 21 deletions

View File

@ -195,9 +195,10 @@ struct psi_threshold {
int threshold_ms; 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 std::unique_ptr<android::bpf::memevents::MemEventListener> memevent_listener(nullptr);
static struct timespec direct_reclaim_start_tm; static struct timespec direct_reclaim_start_tm;
static struct timespec kswapd_start_tm;
static int level_oomadj[VMPRESS_LEVEL_COUNT]; static int level_oomadj[VMPRESS_LEVEL_COUNT];
static int mpevfd[VMPRESS_LEVEL_COUNT] = { -1, -1, -1 }; static int mpevfd[VMPRESS_LEVEL_COUNT] = { -1, -1, -1 };
@ -1591,9 +1592,9 @@ static void ctrl_command_handler(int dsock_idx) {
* waiting, during boot-up, for BPF programs to be loaded. * waiting, during boot-up, for BPF programs to be loaded.
*/ */
if (init_memevent_listener_monitoring()) { if (init_memevent_listener_monitoring()) {
ALOGI("Using memevents for direct reclaim detection"); ALOGI("Using memevents for direct reclaim and kswapd detection");
} else { } else {
ALOGI("Using vmstats for direct reclaim detection"); ALOGI("Using vmstats for direct reclaim and kswapd detection");
if (direct_reclaim_threshold_ms > 0) { if (direct_reclaim_threshold_ms > 0) {
ALOGW("Kernel support for direct_reclaim_threshold_ms is not found"); ALOGW("Kernel support for direct_reclaim_threshold_ms is not found");
direct_reclaim_threshold_ms = 0; direct_reclaim_threshold_ms = 0;
@ -2673,6 +2674,7 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_
bool critical_stall = false; bool critical_stall = false;
bool in_direct_reclaim; bool in_direct_reclaim;
long direct_reclaim_duration_ms; long direct_reclaim_duration_ms;
bool in_kswapd_reclaim;
if (clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm) != 0) { if (clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm) != 0) {
ALOGE("Failed to get current time"); ALOGE("Failed to get current time");
@ -2725,9 +2727,15 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_
swap_low_threshold = 0; swap_low_threshold = 0;
} }
in_direct_reclaim = memevent_listener ? (direct_reclaim_start_tm.tv_sec != 0 || if (memevent_listener) {
direct_reclaim_start_tm.tv_nsec != 0) in_direct_reclaim =
: (vs.field.pgscan_direct != init_pgscan_direct); 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 */ /* Identify reclaim state */
if (in_direct_reclaim) { if (in_direct_reclaim) {
@ -2736,13 +2744,10 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_
init_pgrefill = vs.field.pgrefill; init_pgrefill = vs.field.pgrefill;
direct_reclaim_duration_ms = get_time_diff_ms(&direct_reclaim_start_tm, &curr_tm); direct_reclaim_duration_ms = get_time_diff_ms(&direct_reclaim_start_tm, &curr_tm);
reclaim = DIRECT_RECLAIM; 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_pgscan_kswapd = vs.field.pgscan_kswapd;
init_pgrefill = vs.field.pgrefill; init_pgrefill = vs.field.pgrefill;
reclaim = KSWAPD_RECLAIM; 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) { } else if (workingset_refault_file == prev_workingset_refault) {
/* /*
* Device is not thrashing and not reclaiming, bail out early until we see these stats * Device is not thrashing and not reclaiming, bail out early until we see these stats
@ -3315,17 +3320,25 @@ static void memevent_listener_notification(int data __unused, uint32_t events __
return; return;
} }
/* for (const mem_event_t& mem_event : mem_events) {
* `mem_events` is ordered from oldest to newest, therefore we use switch (mem_event.type) {
* the last/latest direct reclaim event as the current direct reclaim /* Direct Reclaim */
* state. case MEM_EVENT_DIRECT_RECLAIM_BEGIN:
*/ direct_reclaim_start_tm = curr_tm;
for (const mem_event_t mem_event : mem_events) { break;
if (mem_event.type == MEM_EVENT_DIRECT_RECLAIM_BEGIN) { case MEM_EVENT_DIRECT_RECLAIM_END:
direct_reclaim_start_tm = curr_tm; direct_reclaim_start_tm.tv_sec = 0;
} else if (mem_event.type == MEM_EVENT_DIRECT_RECLAIM_END) { direct_reclaim_start_tm.tv_nsec = 0;
direct_reclaim_start_tm.tv_sec = 0; break;
direct_reclaim_start_tm.tv_nsec = 0;
/* 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 +3366,12 @@ static bool init_memevent_listener_monitoring() {
memevent_listener.reset(); memevent_listener.reset();
return false; 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(); int memevent_listener_fd = memevent_listener->getRingBufferFd();
if (memevent_listener_fd < 0) { if (memevent_listener_fd < 0) {