36e8a3
From de72fa6b0582b95216215cc1400412fe91bc8ba3 Mon Sep 17 00:00:00 2001
36e8a3
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
36e8a3
Date: Tue, 22 Jan 2019 16:12:52 +0100
36e8a3
Subject: [PATCH] journal: limit the number of entries in the cache based on
36e8a3
 available memory
36e8a3
36e8a3
This is far from perfect, but should give mostly reasonable values. My
36e8a3
assumption is that if somebody has a few hundred MB of memory, they are
36e8a3
unlikely to have thousands of processes logging. A hundred would already be a
36e8a3
lot. So let's scale the cache size propritionally to the total memory size,
36e8a3
with clamping on both ends.
36e8a3
36e8a3
The formula gives 64 cache entries for each GB of RAM.
36e8a3
36e8a3
(cherry-picked from commit b12a480829c5ca8f4d4fa9cde8716b5f2f12a3ad)
36e8a3
36e8a3
Related: #1664976
36e8a3
---
36e8a3
 src/journal/journald-context.c | 35 ++++++++++++++++++++++++++++++++--
36e8a3
 1 file changed, 33 insertions(+), 2 deletions(-)
36e8a3
36e8a3
diff --git a/src/journal/journald-context.c b/src/journal/journald-context.c
4bff0a
index ce07de1bfb..0f0dc1de4d 100644
36e8a3
--- a/src/journal/journald-context.c
36e8a3
+++ b/src/journal/journald-context.c
36e8a3
@@ -14,6 +14,7 @@
36e8a3
 #include "journal-util.h"
36e8a3
 #include "journald-context.h"
36e8a3
 #include "process-util.h"
36e8a3
+#include "procfs-util.h"
36e8a3
 #include "string-util.h"
36e8a3
 #include "syslog-util.h"
36e8a3
 #include "unaligned.h"
36e8a3
@@ -58,7 +59,37 @@
36e8a3
 /* Keep at most 16K entries in the cache. (Note though that this limit may be violated if enough streams pin entries in
36e8a3
  * the cache, in which case we *do* permit this limit to be breached. That's safe however, as the number of stream
36e8a3
  * clients itself is limited.) */
36e8a3
-#define CACHE_MAX (16*1024)
36e8a3
+#define CACHE_MAX_FALLBACK 128U
36e8a3
+#define CACHE_MAX_MAX (16*1024U)
36e8a3
+#define CACHE_MAX_MIN 64U
36e8a3
+
36e8a3
+static size_t cache_max(void) {
36e8a3
+        static size_t cached = -1;
36e8a3
+
36e8a3
+        if (cached == (size_t) -1) {
36e8a3
+                uint64_t mem_total;
36e8a3
+                int r;
36e8a3
+
36e8a3
+                r = procfs_memory_get(&mem_total, NULL);
36e8a3
+                if (r < 0) {
36e8a3
+                        log_warning_errno(r, "Cannot query /proc/meminfo for MemTotal: %m");
36e8a3
+                        cached = CACHE_MAX_FALLBACK;
36e8a3
+                } else {
36e8a3
+                        /* Cache entries are usually a few kB, but the process cmdline is controlled by the
36e8a3
+                         * user and can be up to _SC_ARG_MAX, usually 2MB. Let's say that approximately up to
36e8a3
+                         * 1/8th of memory may be used by the cache.
36e8a3
+                         *
36e8a3
+                         * In the common case, this formula gives 64 cache entries for each GB of RAM.
36e8a3
+                         */
36e8a3
+                        long l = sysconf(_SC_ARG_MAX);
36e8a3
+                        assert(l > 0);
36e8a3
+
36e8a3
+                        cached = CLAMP(mem_total / 8 / (uint64_t) l, CACHE_MAX_MIN, CACHE_MAX_MAX);
36e8a3
+                }
36e8a3
+        }
36e8a3
+
36e8a3
+        return cached;
36e8a3
+}
36e8a3
 
36e8a3
 static int client_context_compare(const void *a, const void *b) {
36e8a3
         const ClientContext *x = a, *y = b;
36e8a3
@@ -587,7 +618,7 @@ static int client_context_get_internal(
36e8a3
                 return 0;
36e8a3
         }
36e8a3
 
36e8a3
-        client_context_try_shrink_to(s, CACHE_MAX-1);
36e8a3
+        client_context_try_shrink_to(s, cache_max()-1);
36e8a3
 
36e8a3
         r = client_context_new(s, pid, &c);
36e8a3
         if (r < 0)