From 326d7c1b3b8ff8e0bd1dda46ad83a5bf27080e21 Mon Sep 17 00:00:00 2001 From: Daniel Hill Date: Tue, 21 Nov 2023 01:43:52 +1300 Subject: [PATCH] improve kmalloc performance Reading from /proc/meminfo is really slow We don't want to start swapping to disk. Deceptively, memory available goes up when we start to swap to disk making performance even worse. To mitigate this: 1. replace reading from meminfo with proper system calls. 2. attempt to lock allocations in physical memory space. 3. check our own allocated memory instead of available memory. 4. still check available memory in the off chance we're trying to play nice with other apps. Signed-off-by: Daniel Hill Signed-off-by: Kent Overstreet --- bcachefs.c | 2 ++ linux/shrinker.c | 44 ++++++++++---------------------------------- 2 files changed, 12 insertions(+), 34 deletions(-) diff --git a/bcachefs.c b/bcachefs.c index 4efe29ed..b209f63c 100644 --- a/bcachefs.c +++ b/bcachefs.c @@ -187,6 +187,8 @@ static int subvolume_cmds(int argc, char *argv[]) int main(int argc, char *argv[]) { + /* we don't want to swap */ + mlockall(MCL_FUTURE); raid_init(); full_cmd = argv[0]; diff --git a/linux/shrinker.c b/linux/shrinker.c index eae2df6a..dae3d293 100644 --- a/linux/shrinker.c +++ b/linux/shrinker.c @@ -1,5 +1,6 @@ #include +#include #include #include @@ -37,39 +38,14 @@ struct meminfo { u64 available; }; -static u64 parse_meminfo_line(const char *line) -{ - u64 v; - - if (sscanf(line, " %llu kB", &v) < 1) - die("sscanf error"); - return v << 10; -} - void si_meminfo(struct sysinfo *val) { - size_t len, n = 0; - char *line = NULL; - const char *v; - FILE *f; - + long page_size = sysconf(_SC_PAGESIZE); memset(val, 0, sizeof(*val)); val->mem_unit = 1; - f = fopen("/proc/meminfo", "r"); - if (!f) - return; - - while ((len = getline(&line, &n, f)) != -1) { - if ((v = strcmp_prefix(line, "MemTotal:"))) - val->totalram = parse_meminfo_line(v); - - if ((v = strcmp_prefix(line, "MemAvailable:"))) - val->freeram = parse_meminfo_line(v); - } - - fclose(f); - free(line); + val->totalram = sysconf(_SC_PHYS_PAGES) * page_size; + val->freeram = sysconf(_SC_AVPHYS_PAGES) * page_size; } static void run_shrinkers_allocation_failed(gfp_t gfp_mask) @@ -93,6 +69,7 @@ void run_shrinkers(gfp_t gfp_mask, bool allocation_failed) { struct shrinker *shrinker; struct sysinfo info; + struct mallinfo2 malloc_info = mallinfo2(); s64 want_shrink; if (!(gfp_mask & GFP_KERNEL)) @@ -109,16 +86,15 @@ void run_shrinkers(gfp_t gfp_mask, bool allocation_failed) si_meminfo(&info); - if (info.totalram && info.freeram) { - want_shrink = (info.totalram >> 2) - info.freeram; + if (info.totalram && info.totalram >> 4 < info.freeram) { + /* freeram goes up when system swaps, use malloced data instead */ + want_shrink = -malloc_info.arena + (info.totalram / 10 * 8); if (want_shrink <= 0) return; } else { - /* If we weren't able to read /proc/meminfo, we must be pretty - * low: */ - - want_shrink = 8 << 20; + /* We want to play nice with other apps keep 6% avaliable, free 3% */ + want_shrink = (info.totalram >> 5); } mutex_lock(&shrinker_lock);