Hi

here a little patch for FreeBSD to support memory arenas trimming.

Thanks.

regards.
From 1d6386a626f56ca64c25e2dfbf2f9d90a81bd7ae Mon Sep 17 00:00:00 2001
From: David Carlier <devne...@gmail.com>
Date: Wed, 24 Nov 2021 20:02:41 +0000
Subject: [PATCH] MEDIUM: pool: trimming arenas on FreeBSD.

FreeBSD uses a slighty simplified version of jemalloc as libc allocator
since many years (there is thoughts to eventually switch to snmalloc
 but not before a long time).
We detect the libc in the least hacky way in this case aiming as jemalloc
 specific API then we try to purge arenas as much as we can.
---
 include/haproxy/compat.h |  2 +-
 src/pool.c               | 32 ++++++++++++++++++++++++--------
 2 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/include/haproxy/compat.h b/include/haproxy/compat.h
index 25b15a1f0..daa58be5d 100644
--- a/include/haproxy/compat.h
+++ b/include/haproxy/compat.h
@@ -269,7 +269,7 @@ typedef struct { } empty_t;
 #endif
 
 /* FreeBSD also has malloc_usable_size() but it requires malloc_np.h */
-#if defined(USE_MEMORY_PROFILING) && defined(__FreeBSD__) && (__FreeBSD_version >= 700002)
+#if defined(__FreeBSD__) && (__FreeBSD_version >= 700002)
 #include <malloc_np.h>
 #endif
 
diff --git a/src/pool.c b/src/pool.c
index af46b4469..f3ea8c7a7 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -42,8 +42,8 @@ int mem_poison_byte = -1;
 static int mem_fail_rate = 0;
 #endif
 
-#if defined(HA_HAVE_MALLOC_TRIM)
 static int using_libc_allocator = 0;
+#if defined(HA_HAVE_MALLOC_TRIM)
 
 /* ask the allocator to trim memory pools */
 static void trim_all_pools(void)
@@ -82,26 +82,42 @@ static void detect_allocator(void)
 
 	using_libc_allocator = !!memcmp(&mi1, &mi2, sizeof(mi1));
 }
-
-static int is_trim_enabled(void)
-{
-	return using_libc_allocator;
-}
 #else
 
+#if defined(__FreeBSD__)
+extern void sdallocx(void *, size_t, int) __attribute__((weak));
+#endif
+
 static void trim_all_pools(void)
 {
+#if defined(__FreeBSD__)
+	if (using_libc_allocator) {
+		unsigned int narenas = 0;
+		size_t len = sizeof(narenas);
+
+		if (mallctl("arenas.narenas", &narenas, &len, NULL, 0) == 0) {
+			for (unsigned int i = 0; i < narenas; i ++) {
+				char mib[32] = {0};
+				snprintf(mib, sizeof(mib), "arena.%u.purge", i);
+				(void)mallctl(mib, NULL, NULL, NULL, 0);
+			}
+		}
+	}
+#endif
 }
 
 static void detect_allocator(void)
 {
+#if defined(__FreeBSD__)
+	using_libc_allocator = (sdallocx != NULL);
+#endif
 }
+#endif
 
 static int is_trim_enabled(void)
 {
-	return 0;
+	return using_libc_allocator;
 }
-#endif
 
 /* Try to find an existing shared pool with the same characteristics and
  * returns it, otherwise creates this one. NULL is returned if no memory
-- 
2.33.1

Reply via email to