unit_file_find_dirs() is called once for every (unit name or alias, lookup directory, drop-in suffix) combination while enumerating units at boot, to check whether that unit has a ".d", ".wants", ".requires" or ".upholds" drop-in directory in that particular lookup path. On a typical system with ~270 loaded units and ~12 directories in the unit search path, this adds up to tens of thousands of calls. For every one of those calls, the function used to independently re-derive the full chain of candidate unit names to check for that one directory: the name itself, its template if it is a template instance, and its "-" prefix chain (e.g. for "foo-bar-waldo.service" also "foo-bar-.service" and "foo-.service"), recursively expanding further where applicable. That derivation only depends on the unit name itself and does not involve the lookup directory at all, so it produces the exact same list of candidate names regardless of which of the 12 lookup directories is currently being checked. Despite this, it was being fully recomputed for every single directory, doing several small allocations and unit-name parsing calls (unit_name_template(), unit_name_to_prefix(), unit_name_build_from_type(), ...) each time. Split the name-derivation logic out into its own function, unit_file_expand_dropin_names(), and compute it once per unit name/alias, then reuse the resulting candidate list across all lookup directories instead of re-deriving it for each of them. The order in which candidate directories end up being added is unchanged, so this is not expected to alter drop-in resolution behaviour: I confirmed this by comparing the sorted unit load state, fragment path and drop-in path output of "systemd --test --system" before and after this change on the same unit tree, which is byte-for-byte identical. I measured the effect by instrumenting manager_enumerate() with CLOCK_MONOTONIC timestamps and running systemd, built from this exact tree, as actual PID 1 in a container with ~270 real units loaded, 50 runs each before and after this change: before: mean 45.35ms (stddev 0.60ms) after: mean 38.81ms (stddev 0.81ms) a ~14% reduction with about 8 standard deviations of separation between the two distributions, i.e. well outside of run-to-run noise. unit_file_expand_dropin_names()'s out parameter is renamed from ret_names to names, since it is appended to (including recursively) rather than only being populated on success, matching the ret_ naming convention used elsewhere for output-only parameters. Also, a failure partway through expanding a name's candidates (e.g. OOM) no longer discards the candidates already derived before the failure, keeping unit_file_find_dirs() closer to the original recursive implementation's error handling. unit_file_add_dir_if_exists(), which builds the path to check for each (lookup directory, candidate name) pair, is now the hottest remaining part of this code: with the per-directory re-derivation gone, it is called once for every directory/candidate combination instead of once per candidate. It used to build that path with strjoin(name, suffix) followed by path_join(unit_path, name_and_suffix), i.e. two heap allocations plus path_join()'s normalization pass. Lookup paths are already normalized (path_simplify() + strv_uniq()), so a single strjoin(unit_path, "/", name, suffix) produces the same string while halving the allocations and skipping the redundant normalization.
System and Service Manager
Details
Most documentation is available on systemd's web site.
Assorted, older, general information about systemd can be found in the systemd Wiki.
Information about build requirements is provided in the README file.
Consult our NEWS file for information about what's new in the most recent systemd versions.
Please see the Code Map for information about this repository's layout and content.
Please see the Hacking guide for information on how to hack on systemd and test your modifications.
Please see our Contribution Guidelines for more information about filing GitHub Issues and posting GitHub Pull Requests.
When preparing patches for systemd, please follow our Coding Style Guidelines.
If you are looking for support, please contact our mailing list, join our IRC channel #systemd on libera.chat or Matrix channel
Stable branches with backported patches are available in the stable repo.
We have a security bug bounty program sponsored by the Sovereign Tech Fund hosted on YesWeHack
Repositories with distribution packages built from git main are available on OBS, and also repositories with packages built from the latest stable release
