Another small speedup... preloading kernel modules

I spent some time doing some research on a USB drive caching error that pops up. The supposed solution is to enter usb_storage in /etc/modules.

That didn't work to get rid of the issue, but it got me to thinking... during boot, the machine has to scan all the hardware, then scan through a huge set of potential kernel modules to load...


modprobe -c | wc -l
47415

... although the majority of that are aliases.

If you do:

modprobe -c | awk -F ' ' '{print $3}' | sort | uniq | wc -l
5314

You can list them all via:
modprobe -c | awk -F ' ' '{print $3}' | sort | uniq


... what if all those kernel modules used were already loaded?

So I issued:
lsmod

That gave me all the kernel modules being loaded. I figured it'd speed things up if they were loaded by order of when they were used, and since it's not really possible to find that information, I used the module dependencies and the general loading order during boot.

So I had a long list:

Summary
Module                  Size  Used by
rfcomm                 81920  4
bnep                   28672  2
sch_fq_codel           24576  1
cmac                   16384  6
ccm                    20480  6
algif_skcipher         16384  3
algif_hash             16384  3
af_alg                 32768  14 algif_hash,algif_skcipher
snd_hda_codec_realtek   155648  1
snd_hda_codec_hdmi     77824  1
snd_hda_codec_generic   102400  1 snd_hda_codec_realtek
snd_ctl_led            24576  0
ledtrig_audio          16384  2 snd_ctl_led,snd_hda_codec_generic
snd_acp3x_rn           16384  2
snd_soc_dmic           16384  1
snd_acp3x_pdm_dma      16384  1
snd_soc_core          335872  3 snd_acp3x_rn,snd_soc_dmic,snd_acp3x_pdm_dma
snd_hda_intel          53248  8
snd_usb_audio         356352  3
snd_intel_dspcfg       28672  1 snd_hda_intel
rtw88_8822ce           16384  0
snd_intel_sdw_acpi     20480  1 snd_intel_dspcfg
rtw88_8822c           503808  1 rtw88_8822ce
snd_compress           24576  1 snd_soc_core
snd_hda_codec         163840  4 snd_hda_codec_generic,snd_hda_codec_hdmi,snd_hda_intel,snd_hda_codec_realtek
uvcvideo              106496  0
ac97_bus               16384  1 snd_soc_core
snd_pcm_dmaengine      16384  1 snd_soc_core
crct10dif_pclmul       16384  1
ghash_clmulni_intel    16384  0
snd_usbmidi_lib        45056  1 snd_usb_audio
snd_hda_core          110592  5 snd_hda_codec_generic,snd_hda_codec_hdmi,snd_hda_intel,snd_hda_codec,snd_hda_codec_realtek
aesni_intel           376832  13
snd_hwdep              16384  2 snd_usb_audio,snd_hda_codec
btusb                  61440  0
btrtl                  24576  1 btusb
snd_pci_acp6x          16384  0
rtw88_pci              32768  1 rtw88_8822ce
snd_pcm               135168  14 snd_hda_codec_hdmi,snd_pci_acp6x,snd_hda_intel,snd_usb_audio,snd_hda_codec,snd_compress,snd_soc_core,snd_hda_core,snd_acp3x_pdm_dma,snd_pcm_dmaengine
snd_seq_midi           20480  0
videobuf2_vmalloc      20480  1 uvcvideo
rtw88_core            262144  2 rtw88_pci,rtw88_8822c
snd_seq_midi_event     16384  1 snd_seq_midi
btbcm                  24576  1 btusb
videobuf2_memops       20480  1 videobuf2_vmalloc
videobuf2_v4l2         32768  1 uvcvideo
snd_rawmidi            45056  2 snd_seq_midi,snd_usbmidi_lib
videobuf2_common       77824  4 videobuf2_vmalloc,videobuf2_v4l2,uvcvideo,videobuf2_memops
btintel                40960  1 btusb
bluetooth             696320  31 btrtl,btintel,btbcm,bnep,btusb,rfcomm
snd_seq                73728  2 snd_seq_midi,snd_seq_midi_event
mac80211             1261568  2 rtw88_pci,rtw88_core
crypto_simd            16384  1 aesni_intel
cryptd                 24576  5 crypto_simd,ghash_clmulni_intel
binfmt_misc            24576  1
exfat                  86016  1
ecdh_generic           16384  1 bluetooth
snd_seq_device         16384  3 snd_seq,snd_seq_midi,snd_rawmidi
input_leds             16384  0
videodev              253952  3 videobuf2_v4l2,uvcvideo,videobuf2_common
serio_raw              20480  0
snd_timer              40960  2 snd_seq,snd_pcm
nls_iso8859_1          16384  2
mc                     61440  5 videodev,snd_usb_audio,videobuf2_v4l2,uvcvideo,videobuf2_common
joydev                 28672  0
cfg80211              978944  2 rtw88_core,mac80211
snd                   102400  38 snd_ctl_led,snd_hda_codec_generic,snd_seq,snd_seq_device,snd_hda_codec_hdmi,snd_hwdep,snd_hda_intel,snd_usb_audio,snd_usbmidi_lib,snd_hda_codec,snd_hda_codec_realtek,snd_timer,snd_compress,snd_soc_core,snd_pcm,snd_rawmidi
ecc                    36864  1 ecdh_generic
soundcore              16384  2 snd_ctl_led,snd
snd_pci_acp5x          20480  0
snd_rn_pci_acp3x       20480  0
snd_pci_acp3x          20480  0
libarc4                16384  1 mac80211
hid_multitouch         32768  0
mac_hid                16384  0
xt_hl                  16384  22
ip6t_rt                20480  3
ip6t_REJECT            16384  3
hp_wmi                 20480  0
nf_reject_ipv6         20480  1 ip6t_REJECT
wmi_bmof               16384  0
platform_profile       16384  1 hp_wmi
sparse_keymap          16384  1 hp_wmi
xt_limit               16384  1
xt_addrtype            16384  4
acpi_tad               16384  0
xt_tcpudp              20480  20
xt_conntrack           16384  14
nf_conntrack          172032  1 xt_conntrack
nf_defrag_ipv6         24576  1 nf_conntrack
nf_defrag_ipv4         16384  1 nf_conntrack
edac_mce_amd           36864  0
libcrc32c              16384  1 nf_conntrack
kvm_amd               155648  0
kvm                  1015808  1 kvm_amd
ipt_REJECT             16384  3
nf_reject_ipv4         16384  1 ipt_REJECT
ccp                   102400  1 kvm_amd
ip6table_filter        16384  1
k10temp                16384  0
ip6_tables             32768  53 ip6table_filter
rapl                   20480  0
iptable_filter         16384  1
intel_rapl_msr         20480  0
bpfilter               16384  0
intel_rapl_common      40960  1 intel_rapl_msr
msr                    16384  0
ramoops                28672  0
reed_solomon           28672  1 ramoops
pstore_blk             16384  0
pstore_zone            32768  1 pstore_blk
efi_pstore             16384  0
ip_tables              32768  9 iptable_filter
x_tables               53248  12 ip6table_filter,xt_conntrack,iptable_filter,xt_tcpudp,xt_addrtype,ip6t_rt,ip6_tables,ipt_REJECT,ip_tables,xt_limit,xt_hl,ip6t_REJECT
autofs4                45056  2
zfs                  3821568  23
zunicode              348160  1 zfs
zzstd                 487424  1 zfs
zlua                  163840  1 zfs
zavl                   20480  1 zfs
icp                   323584  1 zfs
zcommon               106496  2 zfs,icp
znvpair                98304  2 zfs,zcommon
spl                   122880  6 zfs,icp,zzstd,znvpair,zcommon,zavl
ses                    20480  0
enclosure              16384  1 ses
scsi_transport_sas     45056  1 ses
usbhid                 65536  0
uas                    28672  3
usb_storage            77824  10 uas
amdgpu               9814016  21
iommu_v2               24576  1 amdgpu
gpu_sched              45056  1 amdgpu
i2c_algo_bit           16384  1 amdgpu
drm_ttm_helper         16384  1 amdgpu
ttm                    86016  2 amdgpu,drm_ttm_helper
drm_kms_helper        307200  1 amdgpu
syscopyarea            16384  1 drm_kms_helper
sysfillrect            20480  1 drm_kms_helper
sysimgblt              16384  1 drm_kms_helper
fb_sys_fops            16384  1 drm_kms_helper
cec                    77824  1 drm_kms_helper
hid_generic            16384  0
ahci                   45056  4
xhci_pci               24576  0
i2c_hid_acpi           16384  0
rc_core                61440  1 cec
crc32_pclmul           16384  0
i2c_hid                36864  1 i2c_hid_acpi
drm                   614400  13 gpu_sched,drm_kms_helper,amdgpu,drm_ttm_helper,ttm
i2c_piix4              28672  0
libahci                45056  1 ahci
xhci_pci_renesas       20480  1 xhci_pci
wmi                    32768  2 hp_wmi,wmi_bmof
video                  57344  0
hid                   147456  4 i2c_hid,usbhid,hid_multitouch,hid_generic

So what I did is to take one of those above that have a "Used by" in the right-hand column, then search for all those dependencies.

So, for instance:

ecc                    36864  1 ecdh_generic
ecdh_generic           16384  1 bluetooth
bluetooth             696320  31 btrtl,btintel,btbcm,bnep,btusb,rfcomm
btrtl                  24576  1 btusb
btintel                40960  1 btusb
btbcm                  24576  1 btusb
bnep                   28672  2
btusb                  61440  0
rfcomm                 81920  4

I did that for each category (UEFI, CPU, memory, GPU, crypto, USB, storage, network, WiFi, Bluetooth, etc.), and arranged each category in the order that the system checks things.

Then I simply stripped off the extraneous information. For instance:

ecc
ecdh_generic
bluetooth
btrtl
btintel
btbcm
bnep
btusb
rfcomm

There were some modules I didn't know which category to put into. I used modinfo and web searches to figure out what those modules did. So, for instance:
modinfo btusb

description: Generic Bluetooth USB driver ver 0.8

Once that was all done, I created a manual ZFS snapshot (so I could roll back if what I was doing borked things), then saved /etc/modules with the long list of modules to pre-load, then rebooted.

The result? The total load time to Run Level 5 (the desktop) was reduced by ~1 second... the kernel time to load the modules was front-loaded and all-at-once and it took 10.656s, but once the modules were loaded, it was at the desktop in only 6.785s.

If I could figure out some way of moving all the boot files to the fastest part of the disk and locking them there (so they can't be moved), it'd probably shave another second off that time. They'd be loaded without the drive having to seek much.

This would likely have a far greater effect on a machine with a SSD... the modules would pre-load without any seek time, so the boot would be somewhere around 8 seconds total on this machine.

2 Likes