From 735d3518896827c86481b53182bb47a507e38681 Mon Sep 17 00:00:00 2001 From: Antonio Alvarez Feijoo Date: Wed, 8 Apr 2026 10:46:02 +0200 Subject: [PATCH] perf(dracut-functions): optimize inst_libdir_file() Let's start analyzing the output of a non-hostonly build, focusing on the `inst_libdir_file()` calls: ``` $ dracut -f -N --debug testn.img 2>&1 &> testn.txt $ grep -r -c "(inst_libdir_file): inst_multiple" testn.txt 17 $ grep -r "(inst_libdir_file): inst_multiple" testn.txt | awk -F"inst_multiple " '{ print $2 }' | tr ' ' '\n' | sort | wc -l 295 $ grep -r "(inst_libdir_file): inst_multiple" testn.txt | awk -F"inst_multiple " '{ print $2 }' | tr ' ' '\n' | sort -u | wc -l 201 ``` There are 94 files that are attempted to be installed multiple times. After adding a simple cache: ``` $ grep -r -c "(inst_libdir_file): inst_multiple" testn2.txt 13 $ grep -r "(inst_libdir_file): inst_multiple" testn2.txt | awk -F"inst_multiple " '{ print $2 }' | tr ' ' '\n' | sort | wc -l 201 ``` --- dracut-functions.sh | 19 +++++++++++++++++-- test/test-functions | 4 ++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/dracut-functions.sh b/dracut-functions.sh index 8d4785ddae..36ca5e6633 100755 --- a/dracut-functions.sh +++ b/dracut-functions.sh @@ -1336,6 +1336,13 @@ inst_libdir_dir() { # -n install matching files inst_libdir_file() { local -a _files=() + local _path + + # cache installed libdir files + if ! declare -p _libdir_file_cache 2> /dev/null | grep -q "declare -A"; then + declare -gxA _libdir_file_cache=() + fi + if [[ $1 == "-n" ]]; then local _pattern=$2 shift 2 @@ -1343,7 +1350,11 @@ inst_libdir_file() { for _i in "$@"; do for _f in "${dracutsysrootdir-}$_dir"/$_i; do [[ ${_f#"${dracutsysrootdir-}"} =~ $_pattern ]] || continue - [[ -e $_f ]] && _files+=("${_f#"${dracutsysrootdir-}"}") + _path="${_f#"${dracutsysrootdir-}"}" + if [[ -e $_f ]] && [[ ${_libdir_file_cache[$_path]:-} != 1 ]]; then + _files+=("$_path") + _libdir_file_cache[$_path]=1 + fi done done done @@ -1351,7 +1362,11 @@ inst_libdir_file() { for _dir in $libdirs; do for _i in "$@"; do for _f in "${dracutsysrootdir-}$_dir"/$_i; do - [[ -e $_f ]] && _files+=("${_f#"${dracutsysrootdir-}"}") + _path="${_f#"${dracutsysrootdir-}"}" + if [[ -e $_f ]] && [[ ${_libdir_file_cache[$_path]:-} != 1 ]]; then + _files+=("$_path") + _libdir_file_cache[$_path]=1 + fi done done done diff --git a/test/test-functions b/test/test-functions index 8b76dc649a..a84c026f34 100644 --- a/test/test-functions +++ b/test/test-functions @@ -93,6 +93,10 @@ build_rootfs_base() { # Include os-release to make systemd's initrd-switch-root.service happy cp /usr/lib/os-release "$rootdir/usr/lib/os-release" + # Unset cache variables, otherwise successive calls to build_rootfs_base() + # to generate another initrd would not install the required files + unset _libdir_file_cache + if [[ "$(type -t inst_multiple 2> /dev/null)" != "function" ]]; then # shellcheck source=./dracut-functions.sh . "$PKGLIBDIR/dracut-functions.sh"