Analyze Linux Boot Performance with systemd

Measure Linux boot time, find critical startup dependencies, create boot charts, inspect logs, and verify improvements with systemd-analyze.

systemd-analyze reports timing and dependency information collected by the systemd manager. It can measure the current boot, rank unit activation times, identify the time-critical dependency chain, create an SVG timeline, and validate unit files.

Official references:

Establish a Baseline

Confirm that systemd is the active service manager and record its version.

ps -p 1 -o pid,comm,args
systemd-analyze --version
systemctl get-default

Measure the current boot.

systemd-analyze time

Running systemd-analyze without a subcommand is equivalent.

systemd-analyze

A typical result separates several phases:

Startup finished in 6.112s (firmware) + 1.834s (loader) + 3.927s (kernel) + 4.215s (initrd) + 8.406s (userspace) = 24.495s
graphical.target reached after 8.102s in userspace
Phase Meaning
Firmware UEFI or system firmware initialization
Loader Bootloader time before starting the kernel
Kernel Kernel initialization before the initrd or system manager
Initrd Initial RAM filesystem initialization
Userspace Systemd unit activation up to the reported target

Firmware and loader timings are available only on supported boot environments. Containers usually report userspace time only.

The total does not mean that every application is fully initialized or that disks and network services are idle. It measures elapsed time until systemd has spawned the services required by the target and those jobs have reached the states systemd considers started.

For meaningful comparisons, measure several cold boots under similar conditions. Firmware caches, filesystem caches, pending updates, network availability, and attached hardware can change the result.

Rank Unit Activation Times

List loaded units by the time they spent activating.

systemd-analyze blame

Show the first 30 entries without opening a pager.

systemd-analyze blame --no-pager | head -n 30

Treat this list as a set of candidates rather than proof of causation:

  • Services start in parallel, so several long activations may overlap.
  • A service can appear slow because it waits for another service, device, mount, or network event.
  • Units that move directly from inactive to active may not have a measurable activating period.
  • Type=simple services are considered started immediately and normally do not show their real application initialization time.
  • The list measures activation time, not time spent waiting in systemd’s job queue.

Inspect the dependencies and logs before disabling or modifying a high-ranking unit.

Find the Critical Chain

Display the time-critical dependency chain for the default target.

systemd-analyze critical-chain

Analyze the chain leading to a specific service.

systemd-analyze critical-chain nginx.service

Analyze the chain leading to the graphical target explicitly.

systemd-analyze critical-chain graphical.target

In the output, @ shows when a unit became active relative to boot, and + shows how long that unit spent activating.

graphical.target @8.102s
└─multi-user.target @8.101s
  └─example.service @3.400s +4.699s

Use --fuzz to include nearby branches that completed shortly before the latest dependency at each level.

systemd-analyze critical-chain --fuzz=1s

The critical chain also has limits. Socket activation, parallel execution, and jobs that never enter a measurable activating state can make the output incomplete. It does not display every timeout or every possible dependency branch.

Create a Boot Timeline

Generate an SVG chart showing unit activation across the boot timeline.

systemd-analyze plot > boot.svg

Open boot.svg in a browser or vector-image viewer. The chart makes overlapping unit activations easier to see and helps distinguish one long critical path from several unrelated background operations.

Check that the output is an SVG document before sharing it.

file boot.svg

Recent systemd versions can also print the plot data as a table.

systemd-analyze plot --table

If --table is unavailable on the installed version, use the SVG output.

Graph Unit Dependencies

The dot command generates a dependency graph in Graphviz format. Install Graphviz first if the dot renderer is missing.

On Ubuntu or Debian:

sudo apt update
sudo apt install -y graphviz

Render the complete dependency graph as SVG. A full system graph can be very large.

systemd-analyze dot | dot -Tsvg > systemd-dependencies.svg

Limit the graph to relationships leading to one service.

systemd-analyze dot --to-pattern='nginx.service' | dot -Tsvg > nginx-dependencies.svg

Dependency graphs show declared relationships; they do not directly show which process consumed CPU, waited for storage, or stalled on an external network response.

Inspect Boot Logs with Monotonic Time

Display current-boot messages with timestamps measured from the start of the boot.

sudo journalctl -b -o short-monotonic

Show warnings and more severe messages from the current boot.

sudo journalctl -b -p warning --no-pager

Search for common timeout and dependency failures.

sudo journalctl -b --grep='timed out|A start job is running|Dependency failed|Failed to start' --case-sensitive=no

Inspect one candidate service.

systemctl status nginx.service --no-pager --full
sudo journalctl -u nginx.service -b -o short-monotonic --no-pager

Inspect kernel initialization separately.

sudo journalctl -k -b -o short-monotonic

List retained boots and read the previous boot’s logs.

journalctl --list-boots
sudo journalctl -b -1 -o short-monotonic

systemd-analyze reports live timing data from the current manager. Use retained journal entries and saved reports when comparing the current boot with an earlier one.

Inspect Unit Timing and Configuration

Display timestamps, result state, and the source unit file for a candidate service.

systemctl show nginx.service --property=ActiveEnterTimestamp,ActiveEnterTimestampMonotonic,InactiveExitTimestampMonotonic,ExecMainStartTimestampMonotonic,Result,FragmentPath,DropInPaths

Display the complete vendor unit and every applied drop-in.

systemctl cat nginx.service

Display direct and reverse dependencies.

systemctl list-dependencies nginx.service --all
systemctl list-dependencies nginx.service --reverse

Remember that dependency and ordering directives have different roles. Wants= and Requires= describe dependency strength, while After= and Before= determine order when both units participate in the same transaction.

Check for Failed Units

List units in the failed state.

systemctl --failed

Inspect one failure and its journal.

systemctl status example.service --no-pager --full
sudo journalctl -u example.service -b -n 100 --no-pager

A failed unit does not always delay the critical path, but repeated retries, dependency timeouts, and required units can extend boot time.

Validate Unit Files

Verify a custom or modified unit before reloading systemd.

sudo systemd-analyze verify /etc/systemd/system/example.service

After a manual edit, reload the manager and restart the affected service.

sudo systemctl daemon-reload
sudo systemctl restart example.service

Use systemctl edit for local overrides of package-provided units so upgrades do not replace the changes.

sudo systemctl edit example.service

Analyze the User Service Manager

Desktop startup can continue after the system target is reached. Analyze services belonging to the current user separately.

systemd-analyze --user time
systemd-analyze --user blame
systemd-analyze --user critical-chain
systemctl --user --failed

These commands require an active user systemd manager and describe user units rather than system services.

Investigate Network Wait Services

Network-online wait services are common near the top of a blame list. Before disabling one, find which units require network-online.target.

systemctl list-dependencies network-online.target --reverse

Inspect the active wait implementation and its logs. The unit name depends on the network manager.

systemctl status systemd-networkd-wait-online.service --no-pager --full
sudo journalctl -u systemd-networkd-wait-online.service -b --no-pager

For NetworkManager-based systems:

systemctl status NetworkManager-wait-online.service --no-pager --full
sudo journalctl -u NetworkManager-wait-online.service -b --no-pager

Do not disable a wait-online service until you confirm that no required mount, database, backup, or application needs a usable network during boot. Correcting an unused interface, DHCP timeout, or overly broad online requirement is safer than hiding the delay.

Optimize Boot Safely

Use this workflow for each proposed change:

  1. Record systemd-analyze time, blame, critical-chain, failed units, and relevant boot logs.
  2. Identify whether the delay belongs to firmware, bootloader, kernel, initrd, or userspace.
  3. Confirm that a slow userspace unit lies on the critical chain or blocks a required dependency.
  4. Read the unit file and journal to find the actual wait condition.
  5. Change one setting at a time with a drop-in or the application’s supported configuration.
  6. Reboot under comparable conditions and repeat the measurements.
  7. Restore the original setting if the improvement is not repeatable or removes required behavior.

Disable a service only after confirming that the machine does not need it.

sudo systemctl disable --now example.service

Socket- or timer-activated services may not need to start at boot. Inspect the related units before changing them.

systemctl list-dependencies example.service --reverse
systemctl list-unit-files 'example.*'
systemctl cat example.service

Avoid masking core system units as a performance experiment. Masking blocks manual and dependency-based activation and can make the system unusable.

Save a Report for Comparison

Create a directory and save the main reports after each test boot.

mkdir -p ~/boot-analysis
systemd-analyze time | tee ~/boot-analysis/time.txt
systemd-analyze blame --no-pager > ~/boot-analysis/blame.txt
systemd-analyze critical-chain --no-pager > ~/boot-analysis/critical-chain.txt
systemd-analyze plot > ~/boot-analysis/boot.svg
systemctl --failed --no-pager > ~/boot-analysis/failed-units.txt
sudo journalctl -b -p warning --no-pager > ~/boot-analysis/boot-warnings.txt

Record the kernel, systemd version, and boot ID with the report.

uname -a > ~/boot-analysis/system.txt
systemd-analyze --version >> ~/boot-analysis/system.txt
cat /proc/sys/kernel/random/boot_id >> ~/boot-analysis/system.txt

Some logs may contain hostnames, device identifiers, IP addresses, usernames, command arguments, or application data. Review the report before sharing it.

Troubleshooting

systemd-analyze blame Shows Almost Nothing

Confirm that the system booted with systemd as PID 1. Containers and WSL environments may not provide complete firmware, kernel, or service timing data. Services using Type=simple also do not expose meaningful activation duration.

ps -p 1 -o pid,comm,args
systemd-analyze time

A Long Service Is Missing from the Critical Chain

It may have started in parallel without delaying the target, been socket-activated, or never entered a measurable activating state. Inspect its timestamps, dependencies, and journal directly.

systemctl show example.service --property=ActiveEnterTimestampMonotonic,InactiveExitTimestampMonotonic,Result
systemctl list-dependencies example.service --all
sudo journalctl -u example.service -b -o short-monotonic

Userspace Is Fast but the Total Boot Is Slow

Look at the firmware, loader, kernel, and initrd fields in systemd-analyze time. Systemd service changes cannot reduce time spent before userspace. Firmware settings, device initialization, bootloader timeouts, storage detection, kernel messages, and initrd configuration require separate investigation.

systemd-analyze time
sudo journalctl -k -b -o short-monotonic

Results Change Substantially Between Boots

Repeat several cold boots with the same peripherals and network conditions. Check for DHCP delays, storage errors, update jobs, filesystem checks, and services that contact external systems during startup.

sudo journalctl -b -p warning --no-pager
systemd-analyze critical-chain
Licensed under CC BY-NC-SA 4.0
Last updated on Thursday, September 24, 2026
comments powered by Disqus