[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: