]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
manager: free the jobs hashmap after we have no jobs 15954/head
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 28 May 2020 16:39:27 +0000 (18:39 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 28 May 2020 16:54:20 +0000 (18:54 +0200)
After a larger transaction, e.g. after bootup, we're left with an empty hashmap
with hundreds of buckets. Long-term, it'd be better to size hashmaps down when
they are less than 1/4 full, but even if we implement that, jobs hashmap is
likely to be empty almost always, so it seems useful to deallocate it once the
jobs count reaches 0.

src/core/job.c
src/core/manager.c
src/core/transaction.c

index cf3bca88d63043c59d24c91ccac5ab768cc914f2..d518ac896936971ccf9b6db4c18096b5d3aedda3 100644 (file)
@@ -263,6 +263,10 @@ int job_install_deserialized(Job *j) {
                 return log_unit_debug_errno(j->unit, SYNTHETIC_ERRNO(EEXIST),
                                             "Unit already has a job installed. Not installing deserialized job.");
 
+        r = hashmap_ensure_allocated(&j->manager->jobs, NULL);
+        if (r < 0)
+                return r;
+
         r = hashmap_put(j->manager->jobs, UINT32_TO_PTR(j->id), j);
         if (r == -EEXIST)
                 return log_unit_debug_errno(j->unit, r, "Job ID %" PRIu32 " already used, cannot deserialize job.", j->id);
index 7acbbb0b9ea26457d52a3eb55363886ab8afab38..3659bb0d59006e0461e39a3ec67c5d39134f9a7e 100644 (file)
@@ -833,10 +833,6 @@ int manager_new(UnitFileScope scope, ManagerTestRunFlags test_run_flags, Manager
         if (r < 0)
                 return r;
 
-        r = hashmap_ensure_allocated(&m->jobs, NULL);
-        if (r < 0)
-                return r;
-
         r = hashmap_ensure_allocated(&m->cgroup_unit, &path_hash_ops);
         if (r < 0)
                 return r;
@@ -3963,6 +3959,11 @@ void manager_check_finished(Manager *m) {
                 return;
         }
 
+        /* The jobs hashmap tends to grow a lot during boot, and then it's not reused until shutdown. Let's
+           kill the hashmap if it is relatively large. */
+        if (hashmap_buckets(m->jobs) > hashmap_size(m->units) / 10)
+                m->jobs = hashmap_free(m->jobs);
+
         manager_flip_auto_status(m, false, "boot finished");
 
         /* Notify Type=idle units that we are done now */
index 6f614a32dcf78363e707fe522713a7b8744729c8..0fb52372f16a02561e2fe7a93e4975f17856a5f6 100644 (file)
@@ -656,6 +656,10 @@ static int transaction_apply(
                 assert(!j->transaction_prev);
                 assert(!j->transaction_next);
 
+                r = hashmap_ensure_allocated(&m->jobs, NULL);
+                if (r < 0)
+                        return r;
+
                 r = hashmap_put(m->jobs, UINT32_TO_PTR(j->id), j);
                 if (r < 0)
                         goto rollback;