Bug#652525: Takes excessively long time to generate initramfs
Package: initramfs-tools
Version: 0.99
Severity: normal
File: /usr/sbin/update-initramfs
In the last few versions of initramfs-tools, update-initramfs started
taking an excessively long time to generate the initramfs:
~$ time sudo update-initramfs -u
update-initramfs: Generating /boot/initrd.img-3.1.0-1-amd64
real 0m26.197s
user 0m14.785s
sys 0m1.196s
This results in a long delay every time I upgrade either a kernel or any
package with an update-initramfs hook.
As far as I can tell, a large part of this processing time seems to
consist of the per-module processing for the ~500 kernel modules copied
into the initramfs, forking off a pile of programs for each one. I
tried optimizing the per-module hot path to eliminate as many forks as
possible, and managed to speed it up considerably:
~$ time sudo update-initramfs -u
update-initramfs: Generating /boot/initrd.img-3.1.0-1-amd64
real 0m21.385s
user 0m14.393s
sys 0m0.740s
I've attached a patch implementing these optimizations.
A few other possible improvements:
- Generate a list of modules and processing them all in batch at the
end of update-initramfs, to allow calling modprobe and modinfo only
once. Likely to make a huge difference.
- In the absence of the above, make manual_add_modules take a list of
modules and process them all, and make the various hooks pass a list
of modules to manual_add_modules rather than calling it repeatedly.
- Avoid using copy_exec for firmware binaries, to avoid running ldd on
them.
- Cache the contents of /proc/modules and ${CONFDIR}/modules, and
eliminating the call to grep via more magic shell variable tricks.
- Rewrite the whole thing in something less glacial than shell; perhaps
something with bindings to the new libkmod. Or, at least rewrite the
hot paths, and use the shell only to string pieces together.
Hope that helps,
Josh Triplett
-- Package-specific info:
-- initramfs sizes
-- lsmod
Module Size Used by
parport_pc 22364 0
ppdev 12763 0
lp 17149 0
parport 31858 3 parport_pc,ppdev,lp
bnep 17567 2
rfcomm 33622 0
acpi_cpufreq 12935 1
mperf 12453 1 acpi_cpufreq
cpufreq_powersave 12454 0
cpufreq_conservative 13147 0
cpufreq_stats 12866 0
cpufreq_userspace 12576 0
fuse 61981 1
ext3 161848 1
jbd 56928 1 ext3
loop 22597 0
kvm_intel 121792 0
kvm 278183 1 kvm_intel
snd_hda_codec_hdmi 26548 1
snd_hda_codec_conexant 45245 1
joydev 17266 0
arc4 12458 2
thinkpad_acpi 61270 0
snd_seq_midi 12848 0
snd_rawmidi 23060 1 snd_seq_midi
snd_seq_midi_event 13316 1 snd_seq_midi
snd_seq 45093 2 snd_seq_midi,snd_seq_midi_event
snd_hda_intel 26182 4
snd_hda_codec 72920 3 snd_hda_codec_hdmi,snd_hda_codec_conexant,snd_hda_intel
snd_hwdep 13186 1 snd_hda_codec
snd_pcm_oss 41081 0
iwlagn 166592 0
snd_mixer_oss 17916 1 snd_pcm_oss
snd_seq_device 13176 3 snd_seq_midi,snd_rawmidi,snd_seq
mac80211 183093 1 iwlagn
ecb 12737 1
snd_pcm 63744 5 snd_hda_codec_hdmi,snd_hda_intel,snd_hda_codec,snd_pcm_oss
i915 348449 2
psmouse 55543 0
evdev 17562 8
serio_raw 12850 0
drm_kms_helper 27227 1 i915
i2c_i801 16870 0
drm 167371 3 i915,drm_kms_helper
cfg80211 132703 2 iwlagn,mac80211
btusb 17502 2
iTCO_wdt 17081 0
i2c_algo_bit 12841 1 i915
snd_timer 22917 3 snd_seq,snd_pcm
iTCO_vendor_support 12704 1 iTCO_wdt
bluetooth 119290 13 bnep,rfcomm,btusb
snd 52798 19 snd_hda_codec_hdmi,snd_hda_codec_conexant,thinkpad_acpi,snd_rawmidi,snd_seq,snd_hda_intel,snd_hda_codec,snd_hwdep,snd_pcm_oss,snd_mixer_oss,snd_seq_device,snd_pcm,snd_timer
snd_page_alloc 13003 2 snd_hda_intel,snd_pcm
rfkill 19012 4 thinkpad_acpi,cfg80211,bluetooth
battery 13109 0
i2c_core 23876 5 i915,drm_kms_helper,i2c_i801,drm,i2c_algo_bit
soundcore 13065 1 snd
wmi 13243 0
nvram 13049 1 thinkpad_acpi
ac 12624 0
power_supply 13475 2 battery,ac
video 17628 1 i915
button 12937 1 i915
processor 27949 1 acpi_cpufreq
ext4 312988 1
mbcache 13065 2 ext3,ext4
jbd2 62015 1 ext4
crc16 12343 2 bluetooth,ext4
sha256_generic 16797 2
aesni_intel 50643 28
cryptd 14517 9 aesni_intel
aes_x86_64 16796 1 aesni_intel
aes_generic 33026 2 aesni_intel,aes_x86_64
cbc 12754 0
dm_crypt 22586 1
dm_mod 63353 9 dm_crypt
sd_mod 36136 3
crc_t10dif 12348 1 sd_mod
ahci 24997 2
libahci 22860 1 ahci
libata 140545 2 ahci,libahci
scsi_mod 162376 2 sd_mod,libata
xhci_hcd 64215 0
sdhci_pci 13483 0
sdhci 26577 1 sdhci_pci
ehci_hcd 40215 0
mmc_core 63754 1 sdhci
thermal 17383 0
thermal_sys 18040 3 video,processor,thermal
usbcore 124095 4 btusb,xhci_hcd,ehci_hcd
e1000e 125122 0
-- /etc/initramfs-tools/modules
-- /etc/kernel-img.conf
# Kernel image management overrides
# See kernel-img.conf(5) for details
do_symlinks = no
do_bootloader = no
do_initrd = yes
link_in_boot = no
-- /etc/initramfs-tools/initramfs.conf
MODULES=most
BUSYBOX=y
KEYMAP=n
COMPRESS=gzip
BOOT=local
DEVICE=
NFSROOT=auto
-- /etc/initramfs-tools/update-initramfs.conf
update_initramfs=yes
backup_initramfs=no
-- /etc/crypttab
sda2_crypt UUID=346c3b45-ab3d-4a4b-a08c-4aa99b897132 none luks
-- mkinitramfs hooks
/etc/initramfs-tools/hooks/:
/usr/share/initramfs-tools/hooks:
busybox
cryptgnupg
cryptkeyctl
cryptopenct
cryptopensc
cryptpassdev
cryptroot
dmsetup
fuse
keymap
klibc
lvm2
thermal
udev
-- System Information:
Debian Release: wheezy/sid
APT prefers unstable
APT policy: (500, 'unstable'), (500, 'stable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Kernel: Linux 3.1.0-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=C.UTF-8, LC_CTYPE=C.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Versions of packages initramfs-tools depends on:
ii cpio 2.11-7
ii findutils 4.4.2-1+b1
ii klibc-utils 1.5.25-1
ii module-init-tools 3.16-1
ii udev 175-3
Versions of packages initramfs-tools recommends:
ii busybox 1:1.19.3-5
Versions of packages initramfs-tools suggests:
ii bash-completion 1:1.3-1
-- no debconf information
--- /usr/share/initramfs-tools/hook-functions 2011-05-13 02:56:12.000000000 -0700
+++ hook-functions 2011-12-17 22:35:04.553348553 -0800
@@ -42,17 +42,20 @@
# Add dependent modules + eventual firmware
manual_add_modules()
{
- local kmod firmware
+ local prefix kmod firmware
+
+ modprobe --set-version="${version}" --ignore-install --quiet --show-depends "${1}" |
+ while read prefix kmod ; do
+ if [ "${prefix}" != "insmod" ]; then
+ continue
+ fi
- for kmod in $(modprobe --set-version="${version}" --ignore-install \
- --quiet --show-depends "${1}" | awk '/^insmod/ { print $2 }'); do
# Prune duplicates
if [ -e "${DESTDIR}/${kmod}" ]; then
continue
fi
- mkdir -p "${DESTDIR}/$(dirname "${kmod}")"
- cp -pL "${kmod}" "${DESTDIR}/$(dirname "${kmod}")"
+ install -Dpm 644 "$kmod" "${DESTDIR}/$kmod"
if [ "${verbose}" = "y" ]; then
echo "Adding module ${kmod}"
fi
@@ -74,10 +77,9 @@
continue
fi
- if grep -q "^$(basename "${kmod}" .ko)[[:space:]]" \
- /proc/modules \
- || grep -q "^$(basename "${kmod}" .ko)" \
- "${CONFDIR}/modules"; then
+ kmod_modname="${kmod##*/}"
+ kmod_modname="${kmod_modname%.ko}"
+ if grep -q "^$kmod_modname\\>" /proc/modules "${CONFDIR}/modules"; then
echo "W: Possible missing firmware /lib/firmware/${firmware} for module $(basename ${kmod} .ko)" >&2
fi
continue
Reply to: