From a4ac27c1af5fa055a7c71729f71dce0b16cf5385 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 28 May 2020 18:39:27 +0200 Subject: [PATCH] manager: free the jobs hashmap after we have no jobs 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 | 4 ++++ src/core/manager.c | 9 +++++---- src/core/transaction.c | 4 ++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/core/job.c b/src/core/job.c index cf3bca88d63..d518ac89693 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -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); diff --git a/src/core/manager.c b/src/core/manager.c index 7acbbb0b9ea..3659bb0d590 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -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 */ diff --git a/src/core/transaction.c b/src/core/transaction.c index 6f614a32dcf..0fb52372f16 100644 --- a/src/core/transaction.c +++ b/src/core/transaction.c @@ -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; -- 2.47.3