diff --git a/boot/bench_test.go b/boot/bench_test.go index 67a8230..2d0c091 100644 --- a/boot/bench_test.go +++ b/boot/bench_test.go @@ -87,6 +87,9 @@ func without(units ...string) variant { // - tmpfs /tmp against /tmp on the disk: 3 ms, within noise (220/232 against 223/230, 20 // boots, 2026-09-26); image/build.sh forbids the disk. // - serial-getty Type=simple instead of Type=idle: within noise of the echo (2026-09-10). +// And again once spin lingered and user@1000.service was in the boot transaction: 346/358 +// against 423/441, 20 boots, lab run 43362067503 (2026-11-13) - now the image's +// (serial-getty@.service.d/type.conf). // - loop.max_loop=0 8250.nr_uarts=1, and CONFIG_VT=n: no change to a login prompt // (2026-09-26). udev's coldplug overlaps the boot rather than delaying it. // - 19 udev rule files for hardware the machine cannot have, masked: no change, same day. diff --git a/image/build.sh b/image/build.sh index daae0e8..40e282a 100755 --- a/image/build.sh +++ b/image/build.sh @@ -299,6 +299,13 @@ for f in /etc/systemd/system/serial-getty@.service.d/term.conf \ in_image "$f" || { echo "ERROR: the image has no $f; a login would inherit TERM=dumb" >&2; exit 1; } done +# The serial getty is started Type=simple: Type=idle holds it until the boot's job queue +# drains, which with spin lingering is 77 ms of a login prompt (serial-getty@.service.d/type.conf). +"$bin/debugfs" -R "cat /etc/systemd/system/serial-getty@.service.d/type.conf" /work/base.raw 2>/dev/null | + grep -qx 'Type=simple' || { + echo "ERROR: the serial getty is not Type=simple; its prompt waits for the job queue to drain" >&2 + exit 1; } + # A boot optimization that is invisible in a file listing and expensive when it regresses: # a masked unit is a symlink to /dev/null, and a package upgrade replacing one turns it # back on. One of the ones optimize-systemd.sh masked for measured reasons. diff --git a/image/mkosi.extra/usr/local/lib/spin-base/rootfs/etc/systemd/system/serial-getty@.service.d/type.conf b/image/mkosi.extra/usr/local/lib/spin-base/rootfs/etc/systemd/system/serial-getty@.service.d/type.conf new file mode 100644 index 0000000..ffbdb7d --- /dev/null +++ b/image/mkosi.extra/usr/local/lib/spin-base/rootfs/etc/systemd/system/serial-getty@.service.d/type.conf @@ -0,0 +1,14 @@ +# The serial login prompt as soon as its getty is started, not once the boot's job queue drains. +# +# The template is Type=idle: systemd forks the getty and holds it until no job is left running. +# That cost nothing while the queue was empty by then, and Type=simple measured within noise of +# it (2026-09-10). Since spin lingers, logind starts user@1000.service and its chain inside the +# boot transaction, and the getty waited for them: 91.8 ms between its fork and its exec in the +# median boot of v20261113.01 (task boot:waits, lab run 43361486792), against 3-5 before. +# Type=simple gives the prompt 77 ms back - 346/358 against 423/441 ms p50/p95 to a login +# prompt, 20 boots interleaved on the bench fleet (task boot:bench, lab run 43362067503). +# +# What Type=idle is for is a prompt not overwritten by the boot's own status lines, and this +# machine's console prints none: the kernel is quiet and systemd shows no status. +[Service] +Type=simple