JetsonNano起動高速化
JetsonNanoの起動を高速化する。 Systemdサービスで不要なものを止めて起動を高速化してみる。 結果としては倍以上高速化することができた。
制限事項
今回計測するのはKernelが起動してから、初期化処理が終わるまでです。 実際にはその前にBIOSなど(L4TだとBootROMやCboot)が入るので、電源ONからの起動時間は表記+10秒程度はかかっています。
使ったイメージ
Jetpack 4.4イメージを使用した。ただし、パッケージなどいろいろと追加で入れているので参考まで。
ユースケース
自分の使用方法は下のような感じなので、最低限これができる用になればいい。ほかはすべて止める。
現状確認
下のコマンドで起動にかかる時間が調べられる。
$ systemd-analyze Startup finished in 7.068s (kernel) + 4.819s (userspace) = 11.887s graphical.target reached after 4.799s in userspace
現状は11.9秒ほどかかっている模様。
GUI→CLI起動へ変更
CLI起動へ変更する。結果は以下の通り。
$ sudo systemctl set-default multi-user.target $ sudo rebot ~~~ after rebot ~~~ $ systemd-analyze Startup finished in 1.743s (kernel) + 7.076s (userspace) = 8.820s multi-user.target reached after 7.053s in userspace
8.8秒まで短縮された。2.9秒の改善。
解析
以下のコマンドでサービスのうち、起動処理のクリチカルチェインがわかる。 見方としては、@の後ろに書いてある時間がそのサービスが起動開始した時間、+の後ろに書いてある時間が起動にかかった時間である。ちなみに.targetはそれに必要なサービスを集めたものなので、それ自体に処理は存在しない。(例えばmulti-user.target はCLI起動に必要なサービスを集めたもの。Networkなどが含まれる。)
$ systemd-analyze critical-chain The time after the unit is active or started is printed after the "@" character. The time the unit takes to start is printed after the "+" character. multi-user.target @7.053s └─networkd-dispatcher.service @1.247s +5.805s └─basic.target @1.049s └─sockets.target @1.049s └─snapd.socket @1.043s +5ms └─sysinit.target @1.038s └─systemd-timesyncd.service @821ms +217ms └─systemd-tmpfiles-setup.service @701ms +65ms └─local-fs.target @692ms └─local-fs-pre.target @692ms └─keyboard-setup.service @443ms +248ms └─systemd-journald.socket @433ms └─system.slice @429ms └─-.slice @417ms
見てみるとnetworkd-dispatcher.serviceが5.8秒と大きく足を引っ張っていそう。これをどうにかできないか考える。
networkd-dispatcher.serviceって何ぞ?
下記コマンドでサービスの説明や状態が確認できる。 "Dispatcher daemon for systemd-networkd"らしい。わからん。
$ systemctl status networkd-dispatcher.service ● networkd-dispatcher.service - Dispatcher daemon for systemd-networkd Loaded: loaded (/lib/systemd/system/networkd-dispatcher.service; enabled; vendor preset: enabled) Active: active (running) since Thu 2021-01-14 22:08:56 JST; 31min ago Main PID: 3991 (networkd-dispat) Tasks: 2 (limit: 4174) CGroup: /system.slice/networkd-dispatcher.service └─3991 /usr/bin/python3 /usr/bin/networkd-dispatcher --run-startup-triggers ...
どうやらPython3で/usr/bin/networkd-dispatcherを実行しているらしい。中身を見ると、Wifiの設定やリゾルバの設定などを行っていた。以下はNetworkManagerの説明だが、DispacherはNetwork接続時に実行するプログラムを管理するためのものである模様。
また、これはsystemd-networkd用のサービスである。今回はNetworkManagerに統一するので停止してしまう。
$ sudo systemctl disable networkd-dispatcher.service Removed /etc/systemd/system/multi-user.target.wants/networkd-dispatcher.service. $ sudo rebot ~~~ after rebot ~~~ $ systemd-analyze Startup finished in 1.833s (kernel) + 4.640s (userspace) = 6.473s multi-user.target reached after 4.614s in userspace
6.5秒まで短縮した。2.3秒の短縮。
個別にサービス停止
これ以降は大きな差がなかったので、すべてのサービスを見て不要なものは停止する。
$ systemctl -t service UNIT LOAD ACTIVE SUB DESCRIPTION alsa-restore.service loaded active exited Save/Restor apport.service loaded active exited LSB: automa avahi-daemon.service loaded active running Avahi mDNS/ console-setup.service loaded active exited Set console containerd.service loaded active running containerd cron.service loaded active running Regular bac dbus.service loaded active running D-Bus Syste getty@tty1.service loaded active running Getty on tt grub-common.service loaded active exited LSB: Record haveged.service loaded active running Entropy dae kerneloops.service loaded active running Tool to aut keyboard-setup.service loaded active exited Set the con kmod-static-nodes.service loaded active exited Create list ModemManager.service loaded active running Modem Manag networking.service loaded active exited Raise netwo NetworkManager.service loaded active running Network Man nv-l4t-usb-device-mode.service loaded active exited Config nvargus-daemon.service loaded active running Argus daemo nvgetty.service loaded active running UART on tty nvmemwarning.service loaded active running Display Low nvphs.service loaded active running PHS daemon nvs-service.service loaded active running NVS-SERVICE polkit.service loaded active running Authorizati resolvconf.service loaded active exited Nameserver rpcbind.service loaded active running RPC bind po rsyslog.service loaded active running System Logg serial-getty@ttyGS0.service loaded active running Serial Ge serial-getty@ttyS0.service loaded active running Serial Get setvtrgb.service loaded active exited Set console snapd.seeded.service loaded active exited Wait until speech-dispatcher.service loaded active exited LSB: Speech ssh.service loaded active running OpenBSD Sec systemd-journal-flush.service loaded active exited Flush J systemd-journald.service loaded active running Journal Ser systemd-logind.service loaded active running Login Servi systemd-modules-load.service loaded active exited Load Ker systemd-random-seed.service loaded active exited Load/Save systemd-remount-fs.service loaded active exited Remount Ro systemd-resolved.service loaded active running Network Nam systemd-sysctl.service loaded active exited Apply Kerne systemd-timesyncd.service loaded active running Network Tim systemd-tmpfiles-setup-dev.service loaded active exited Cr systemd-tmpfiles-setup.service loaded active exited Create systemd-udev-trigger.service loaded active exited udev Col systemd-udevd.service loaded active running udev Kernel systemd-update-utmp.service loaded active exited Update UT systemd-user-sessions.service loaded active exited Permit ubuntu-fan.service loaded active exited Ubuntu FAN user@1000.service loaded active running User Manage whoopsie.service loaded active running crash repor wpa_supplicant.service loaded active running WPA supplic
- alsa-restore.service: サウンド。停止。
- apport.service: クラッシュ時のログ収集。残す。
- avahi-daemon.service: ローカルネットワーク上のサービス検出(プリンタとか)。停止。
- console-setup.service: コンソールの設定。サービスでわざわざ設定しなくても大丈夫では?停止。
- containerd.service: Dockerの関係者。残す。
- cron.service: プログラムなどを自動実行。停止。
- dbus.service: Dbus。残す。
- getty@tty1.service: TTY。残す。
- grub-common.service: grubのなにか。grubは使ってないので停止。
- ModemManager.service: モデム。使う予定ないので停止。(LTEとかつかうならいるかも。)
ちょっと多すぎるのでここまでで一旦試してみる。
$ sudo systemctl disable alsa-restore.service avahi-daemon.service console-setup.service cron.service grub-common.service ModemManager.service Synchronizing state of avahi-daemon.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install disable avahi-daemon Synchronizing state of cron.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install disable cron grub-common.service is not a native service, redirecting to systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install disable grub-common Removed /etc/systemd/system/dbus-org.freedesktop.Avahi.service. Removed /etc/systemd/system/multi-user.target.wants/console-setup.service. Removed /etc/systemd/system/sockets.target.wants/avahi-daemon.socket. Removed /etc/systemd/system/dbus-org.freedesktop.ModemManager1.service. Removed /etc/systemd/system/multi-user.target.wants/ModemManager.service.
ログを見ると、alsa-restore.service はDisableできていない。このように依存関係などによってDisableできない場合がある。そのときはDisableより強いmaskを使用する。これはそのサービスを/dev/nullにリンクしてしまう。そのため十分に注意して操作を行い、動作確認をしっかり行うこと。
$ sudo systemctl mask alsa-restore.service Created symlink /etc/systemd/system/alsa-restore.service → /dev/null.
これで無効化できた。再起動して起動時間を計測。
$ sudo rebot ~~~ after rebot ~~~ $ systemd-analyze Startup finished in 1.767s (kernel) + 3.764s (userspace) = 5.532s multi-user.target reached after 3.741s in userspace
結果
5.5秒まで短縮。最初と比較すると倍以上高速化することができた。
すべてのサービスは確認できていないので、また時間があるときにつづきやります。
また、maskした影響で、他のサービスがエラーになったりしていないか、下記のコマンドで確認しておく。
$ systemctl -t service