Оптимизация времени загрузки в Arch Linux: Глубокая настройка systemd и сервисов

Сокращение времени загрузки системы — не просто академическое упражнение. Для разработчиков, работающих с физическими серверами, встраиваемыми системами или просто ценящих скорость отклика, каждые 500 мс имеют значение. В Arch Linux, где контроль над системой практически неограничен, инструменты systemd предоставляют детализированный аппарат для оптимизации. Рассмотрим не только рутинное использование systemd-analyze, но и методы тонкой настройки зависимостей, анализа критических цепочек и работы с параметрами ядра.

Анализируем исходное состояние

Начнем с базовой диагностики. Команда systemd-analyze time покажет общее время загрузки ядра (kernel) и пользовательского пространства (userspace). Но настоящая информация скрывается в деталях:

bash
$ systemd-analyze blame --no-pager | head -n 5
          5.212s NetworkManager-wait-online.service
          3.874s dev-sda3.device
          2.945s systemd-cryptsetup@nvme0n1p2.service
          1.879s systemd-udev-settle.service
          874ms docker.service

Эти данные часто вводят в заблуждение. Например, dev-sda3.device выглядит как самодостаточная единица замедления, но на практике это маркер ожидания блочного устройства, которое, в свою очередь, может блокировать другие сервисы. Для выявления фактических зависимостей используем:

bash
$ systemd-analyze critical-chain docker.service
The time after the unit became active or started is printed after the "@" character.
The time the unit took to start is printed after the "+" character.

docker.service @1.879s +874ms
  └─network-online.target @1.878s
    └─NetworkManager-wait-online.service @3.090s +5.212s
      └─NetworkManager.service @875ms +1.682s

Здесь очевидно: docker.service ждет network-online.target, который зависит от медленного NetworkManager-wait-online.service. Это классический случай чрезмерно строгих зависимостей в systemd-юнитах.

Стратегии оптимизации сервисов

Переопределение конфигурации systemd
Маскировка ненужных сервисов (например, ModemManager для серверных установок) — очевидный шаг:

bash
sudo systemctl mask ModemManager.service

Более интересен пример с NetworkManager-wait-online.service. Вместо полного отключения (что нарушит службы, требующие готовой сети), изменим его поведение:

bash
sudo systemctl edit NetworkManager-wait-online.service

Добавляем секцию для ограничения времени ожидания:

ini
[Service]
TimeoutStartSec=10s
ExecStart=
ExecStart=/usr/bin/nm-online -s -q --timeout=10

Модификация ExecStart с предварительной очисткой предыдущего значения (отсюда пустая строка) и установка таймаута уменьшит потенциальный простой.

Параллелизация инициализации
Systemd по умолчанию загружает сервисы с явными зависимостями последовательно. Переход к параллельной загрузке требует декомпозиции зависимостей. Например, для службы docker.service можно устранить зависимость от network-online.target, если приложение допускает временную недоступность сети:

bash
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo nano /etc/systemd/system/docker.service.d/override.conf
ini
[Unit]
After=network.target
Wants=network.target

Это заменяет более строгое After=network-online.target, потенциально выводя запуск docker из критической цепочки сетевой инициализации.

Тонкая настройка ядра и initramfs

Время инициализации ядра (kernel) недооценивают. Анализ через dmesg с timestamp:

bash
$ dmesg -T | grep -E '\[.*\]' | tail -n 5

Вывод покажет узкие места при загрузке устройств. Для SSD и NVMe дисков часто помогает отключение лишних модулей ядра. В файле /etc/mkinitcpio.conf удалите ненужные хуки (например, usbinput для серверов):

diff
-HOOKS=(base systemd autodetect keyboard modconf block sd-encrypt filesystems fsck)
+HOOKS=(base systemd autodetect modconf block sd-encrypt filesystems fsck)

После обновления конфигурации пересобираем образ:

bash
sudo mkinitcpio -P

Для систем с UEFI дополнительный выигрыш дает сокращение времени ожидания загрузчика. В /boot/loader/loader.conf:

ini
timeout 3
console-mode 2

Автоматизация анализа

Статическая оптимизация — только начало. Реализуем динамический мониторинг с помощью systemd-аналитики:

bash
#!/bin/bash
journalctl --boot=0 -o short-monotonic 
  | awk '/Starting User Manager/ {start=1} 
         start && /Starting (.+)\.service/ {svc=$0; sub(/.*Starting /,"",svc); print svc}' 
  | sort | uniq -c | sort -n

Этот скрипт выявляет наиболее часто перезапускаемые сервисы во время загрузки — кандидаты на консолидацию или отложенную инициализацию.

Вывод: баланс скорости и функциональности

Оптимизация времени загрузки в Arch Linux — не гонка за абстрактными миллисекундами. Речь о согласовании системных требований с реальными рабочими сценариями. Осмысленное управление зависимостями systemd, точечная настройка параметров ядра и регулярный анализ через инструменты вроде systemd-analyze plot > boot.svg создают систему, где скорость не противоречит стабильности. Критически важные сервисы сохраняют приоритет, а второстепенные компоненты переходят в фоновый режим — современный подход к управлению временем инициализации.