]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
oom: make memory pressure duration configurable through oomd.conf
authorAnita Zhang <the.anitazha@gmail.com>
Sun, 24 Jan 2021 08:16:19 +0000 (00:16 -0800)
committerAnita Zhang <the.anitazha@gmail.com>
Sun, 24 Jan 2021 09:59:03 +0000 (01:59 -0800)
man/oomd.conf.xml
src/oom/oomd-manager.c
src/oom/oomd-manager.h
src/oom/oomd-util.h
src/oom/oomd.c
src/oom/oomd.conf
test/units/testsuite-56.sh

index 35a0686bc50176b6b094463e2cac714d4ecc6d17..bb5da87c5485930a7679aec6c817c0f1014ac09c 100644 (file)
         will take action. A unit can override this value with <varname>ManagedOOMMemoryPressureLimitPercent=</varname>.
         The memory pressure for this property represents the fraction of time in a 10 second window in which all tasks
         in the cgroup were delayed. For each monitored cgroup, if the memory pressure on that cgroup exceeds the
-        limit set for more than 30 seconds, <command>systemd-oomd</command> will act on eligible descendant cgroups,
+        limit set for longer than the duration set by <varname>DefaultMemoryPressureDurationSec=</varname>,
+        <command>systemd-oomd</command> will act on eligible descendant cgroups,
         starting from the ones with the most reclaim activity to the least reclaim activity. Which cgroups are
         monitored and what action gets taken depends on what the unit has configured for
         <varname>ManagedOOMMemoryPressure=</varname>. Takes a percentage value between 0% and 100%, inclusive.
         Defaults to 60%.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>DefaultMemoryPressureDurationSec=</varname></term>
+
+        <listitem><para>Sets the amount of time a unit's cgroup needs to have exceeded memory pressure limits before
+        <command>systemd-oomd</command> will take action. Memory pressure limits are defined by
+        <varname>DefaultMemoryPressureLimitPercent=</varname> and <varname>ManagedOOMMemoryPressureLimitPercent=</varname>.
+        Defaults to 30 seconds when this property is unset or set to 0.</para></listitem>
+      </varlistentry>
+
     </variablelist>
   </refsect1>
 
index fec96519e01ea21ce530054865294bc496616121..e8ed6a52739b2d71dfd2c7aff9642b3a42e4816a 100644 (file)
@@ -306,7 +306,7 @@ static int monitor_cgroup_contexts_handler(sd_event_source *s, uint64_t usec, vo
                         m->post_action_delay_start = 0;
         }
 
-        r = oomd_pressure_above(m->monitored_mem_pressure_cgroup_contexts, PRESSURE_DURATION_USEC, &targets);
+        r = oomd_pressure_above(m->monitored_mem_pressure_cgroup_contexts, m->default_mem_pressure_duration_usec, &targets);
         if (r == -ENOMEM)
                 return log_error_errno(r, "Failed to check if memory pressure exceeded limits");
         else if (r == 1) {
@@ -325,7 +325,7 @@ static int monitor_cgroup_contexts_handler(sd_event_source *s, uint64_t usec, vo
 
                         SET_FOREACH(t, targets) {
                                 log_notice("Memory pressure for %s is greater than %lu for more than %"PRIu64" seconds and there was reclaim activity",
-                                        t->path, LOAD_INT(t->mem_pressure_limit), PRESSURE_DURATION_USEC / USEC_PER_SEC);
+                                        t->path, LOAD_INT(t->mem_pressure_limit), m->default_mem_pressure_duration_usec / USEC_PER_SEC);
 
                                 r = oomd_kill_by_pgscan(candidates, t->path, m->dry_run);
                                 if (r == -ENOMEM)
@@ -471,7 +471,7 @@ static int manager_connect_bus(Manager *m) {
         return 0;
 }
 
-int manager_start(Manager *m, bool dry_run, int swap_used_limit, int mem_pressure_limit) {
+int manager_start(Manager *m, bool dry_run, int swap_used_limit, int mem_pressure_limit, usec_t mem_pressure_usec) {
         unsigned long l;
         int r;
 
@@ -487,6 +487,8 @@ int manager_start(Manager *m, bool dry_run, int swap_used_limit, int mem_pressur
         if (r < 0)
                 return r;
 
+        m->default_mem_pressure_duration_usec = mem_pressure_usec ?: DEFAULT_MEM_PRESSURE_DURATION_USEC;
+
         r = manager_connect_bus(m);
         if (r < 0)
                 return r;
@@ -505,6 +507,7 @@ int manager_start(Manager *m, bool dry_run, int swap_used_limit, int mem_pressur
 int manager_get_dump_string(Manager *m, char **ret) {
         _cleanup_free_ char *dump = NULL;
         _cleanup_fclose_ FILE *f = NULL;
+        char buf[FORMAT_TIMESPAN_MAX];
         OomdCGroupContext *c;
         size_t size;
         char *key;
@@ -521,10 +524,12 @@ int manager_get_dump_string(Manager *m, char **ret) {
                 "Dry Run: %s\n"
                 "Swap Used Limit: %u%%\n"
                 "Default Memory Pressure Limit: %lu%%\n"
+                "Default Memory Pressure Duration: %s\n"
                 "System Context:\n",
                 yes_no(m->dry_run),
                 m->swap_used_limit,
-                LOAD_INT(m->default_mem_pressure_limit));
+                LOAD_INT(m->default_mem_pressure_limit),
+                format_timespan(buf, sizeof(buf), m->default_mem_pressure_duration_usec, USEC_PER_SEC));
         oomd_dump_system_context(&m->system_context, f, "\t");
 
         fprintf(f, "Swap Monitored CGroups:\n");
index 3f3eb5aa4b64be26990149aed96505767da041dc..ede9903e5a6176b12453fd65de0f56fa42881e93 100644 (file)
@@ -16,7 +16,7 @@
  * percentage of time all tasks were delayed (i.e. unproductive).
  * Generally 60 or higher might be acceptable for something like system.slice with no memory.high set; processes in
  * system.slice are assumed to be less latency sensitive. */
-#define PRESSURE_DURATION_USEC (30 * USEC_PER_SEC)
+#define DEFAULT_MEM_PRESSURE_DURATION_USEC (30 * USEC_PER_SEC)
 #define DEFAULT_MEM_PRESSURE_LIMIT 60
 #define DEFAULT_SWAP_USED_LIMIT 90
 
@@ -33,6 +33,7 @@ struct Manager {
         bool dry_run;
         unsigned swap_used_limit;
         loadavg_t default_mem_pressure_limit;
+        usec_t default_mem_pressure_duration_usec;
 
         /* k: cgroup paths -> v: OomdCGroupContext
          * Used to detect when to take action. */
@@ -53,7 +54,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
 
 int manager_new(Manager **ret);
 
-int manager_start(Manager *m, bool dry_run, int swap_used_limit, int mem_pressure_limit);
+int manager_start(Manager *m, bool dry_run, int swap_used_limit, int mem_pressure_limit, usec_t mem_pressure_usec);
 
 int manager_get_dump_string(Manager *m, char **ret);
 
index 0834cbf09d78445d1532eef2ea7b57a5d1c95c35..d7a9890e7a2d6566372d298effa2a474251ac3f5 100644 (file)
@@ -31,6 +31,7 @@ struct OomdCGroupContext {
 
         /* These are only used by oomd_pressure_above for acting on high memory pressure. */
         loadavg_t mem_pressure_limit;
+        usec_t mem_pressure_duration_usec;
         usec_t last_hit_mem_pressure_limit;
 };
 
index 8cf776ec0f5ff8c6a357996108677931869cf6cf..1b0f8ff6c402677a9a47d57ed73a74ed5b8dd991 100644 (file)
 static bool arg_dry_run = false;
 static int arg_swap_used_limit = -1;
 static int arg_mem_pressure_limit = -1;
+static usec_t arg_mem_pressure_usec = 0;
 
 static int parse_config(void) {
         static const ConfigTableItem items[] = {
                 { "OOM", "SwapUsedLimitPercent",              config_parse_percent, 0, &arg_swap_used_limit    },
                 { "OOM", "DefaultMemoryPressureLimitPercent", config_parse_percent, 0, &arg_mem_pressure_limit },
+                { "OOM", "DefaultMemoryPressureDurationSec",  config_parse_sec,     0, &arg_mem_pressure_usec  },
                 {}
         };
 
@@ -160,7 +162,7 @@ static int run(int argc, char *argv[]) {
         if (r < 0)
                 return log_error_errno(r, "Failed to create manager: %m");
 
-        r = manager_start(m, arg_dry_run, arg_swap_used_limit, arg_mem_pressure_limit);
+        r = manager_start(m, arg_dry_run, arg_swap_used_limit, arg_mem_pressure_limit, arg_mem_pressure_usec);
         if (r < 0)
                 return log_error_errno(r, "Failed to start up daemon: %m");
 
index 8ac971696102695b13fc69b0fcf00462cdd58b41..766cb1717f7b6c62c9e139ebdc2256125bed6161 100644 (file)
@@ -14,3 +14,4 @@
 [OOM]
 #SwapUsedLimitPercent=90%
 #DefaultMemoryPressureLimitPercent=60%
+#DefaultMemoryPressureDurationSec=30s
index 1846248855b0a205cf5935a6fef9edc79eba1409..6e7941a57fc199bab33d3a84c3efc596d9fd10df 100755 (executable)
@@ -14,12 +14,15 @@ if [[ "$cgroup_type" != *"cgroup2"* ]] && [[ "$cgroup_type" != *"0x63677270"* ]]
 fi
 [[ -e /skipped ]] && exit 0 || true
 
+echo "DefaultMemoryPressureDurationSec=5s" >> /etc/systemd/oomd.conf
+
 systemctl start testsuite-56-testbloat.service
 systemctl start testsuite-56-testchill.service
 
 # Verify systemd-oomd is monitoring the expected units
 oomctl | grep "/testsuite-56-workload.slice"
 oomctl | grep "1%"
+oomctl | grep "Default Memory Pressure Duration: 5s"
 
 # systemd-oomd watches for elevated pressure for 30 seconds before acting.
 # It can take time to build up pressure so either wait 5 minutes or for the service to fail.