to other process managers
We ran systemg through a gauntlet of tests against systemd, Supervisor, and Docker Compose — install, boot, memory, teardown, crash recovery, and readiness.
TL;DR: systemg installs faster than Supervisor, boots a dependency graph faster than Docker Compose, and uses less memory than either. It leaves nothing running after you stop a service — so does Compose, where Supervisor strands up to five — and it is the only one of the three that neither duplicates nor loses your workload when the supervisor itself dies.
install to first supervised service
ten-service graph cold boot
supervisor overhead at ten services
0
processes left behind on stop
Install
Getting to a running service
Each tool installed the way its users install it, timed until one service is actually supervised.
to first supervised service
seconds, cold
pulled over the network
megabytes, cold cache
installed on disk
megabytes
systemd ships with the distribution, so its marginal install cost is zero.
3.7×
faster to a supervised service than Supervisor
Supervisor's 48 MB is 47.6 MB of apt index plus 0.4 MB of packages — on a machine that ran apt today it pulls 0.4 MB. sysg pulls 6.8 MB in every cache state. systemd is 14.6 MB installed and ships with the distribution, so its marginal install cost is zero. 86% of Supervisor's disk figure is the CPython runtime; sysg carries its runtime compiled into the binary.
Dependency graph
Ten services, five levels deep
Two independent roots, a five-wide fan-in. Every unit whose dependencies are already satisfied is dispatched at once, so the graph boots in five waves rather than ten steps — concurrency without violating a single edge.
Each bar is one service becoming ready. Playhead is wall-clock.
1.20×
faster than Docker Compose
Supervisor
cannot express this graph
Same graph, same clock. Each marker stops when its last service reports healthy.
Supervisor has no dependency edges. priority orders starts but does not gate on readiness, so this graph cannot be expressed. Compose runs each unit as a container and sysg runs each as a process — different isolation, and Compose ran against the host daemon while sysg ran in a container.
Readiness
Reporting a service as up
A service that starts but cannot do work for five seconds. The marker is when the tool says it is up; the shaded band is the distance from there to when it actually works.
startsecs=5, matched to startup
probe lands on the next 1s tick
Supervisor, default
+3.88s
startsecs=1
Supervisor, 8s service
+2.93s
startsecs=5, startup varies
Band left of the marker is reporting late. Band right of it is reporting early.
startsecs is a fixed timer: set it to the real startup time and it is exact. A probe is closed-loop, so it does not need to be told.
Resident cost
What the supervisor itself costs
Memory for the tool, minus the same services run bare. Ten near-idle services, so the tool dominates. These are orders of magnitude apart, so area is proportional to megabytes.
dockerd + containerd + one containerd-shim per container, measured inside the VM.
28×
less than Docker Compose, at ten services
On macOS, Docker Desktop adds a further 476 MB host-side for the VM and its helpers.
Scaling
Cost per service, as services are added
The intercept matters less than the slope. sysg's exec: argv form runs a service directly instead of through a shell, which removes a resident process per service.
MB overhead
services supervised → · N=500
Fitted from N = 1, 10, 40. Drawn to N = 500.
added MB per service
fitted slope
processes at N=40
supervisor + children
Processes at 40 services. One per service under exec:, two under command:.
command: is unchanged and still spawns through a shell, which stays resident as the service's parent — 85 processes for 40 services instead of 45.
Teardown
Stopping a service that forked children
A service and five descendants, one of which deliberately escapes the process group. Stop it with each tool's own command, then count what is still running.
session teardown reaches the setsid child
container PID namespace collapses
stopasgroup + killasgroup; setsid child escaped the group
Supervisor, default
5 left
signals only the pid it spawned
Filled squares are processes still alive after stop returned.
Survivors reparent to init and keep running. The loss is per stop/restart cycle, so a service that restarts hourly accumulates them.
Control plane
When the supervisor dies
kill -9 the supervisor — dockerd for Compose, not the CLI — then start it again and look at what happened to the workload.
sysg
sysg (new pid)
└─ web pid 77
re-adopted, same pid
Supervisor
supervisord (new)
├─ web pid 77 orphan
└─ web pid 91 duplicate
duplicate started
Docker Compose
dockerd (manual)
└─ web exited
workload terminated
Docker tested at its default live-restore: false.
visible while down
yes
yes
no
no duplicate started
yes
no
yes
recovers unattended
yes
yes
no
Green is the outcome you want, whichever way the question is phrased.
Supervisor's services keep running, but supervisord has no record of them and starts a second copy. With live-restore: false the Docker daemon does not re-attach to containers from the previous session; live-restore: true is untested here. While dockerd was down the workload could not be inspected at all — every path goes through the daemon.
Summary
The process manager for busy people
Numbers where a figure was measured, marks where the answer is yes or no. A dash means it was not measured for that tool.
sysg
systemd
Supervisor
Compose
install to first service
1.49s
—
5.53s
15.85s+
pulled over network
6.8 MB
—
48.0 MB
172.5 MB
installed on disk
19.5 MB
14.6 MB
26.8 MB
278.6 MB
ten-service graph
6.91s
—
n/a
8.31s
overhead at ten services
12.4 MB
—
18.1 MB
354 MB
added per service
0.035 MB
—
0.020 MB
7.26 MB
expresses a dependency graph
gates on a probe, not a timer
leaves nothing behind on stop
—
workload survives its crash
—
starts no duplicate after
—
recovers without an operator
—
runs without a separate runtime
systemd was measured on install size only; its runtime rows need a machine where it is PID 1.
systemg is open source and always welcomes contributors and users. Bugs, benchmark disputes, and re-runs that disagree with anything above are all useful — every script that produced these figures is in the repo, so a contradicting result is a pull request rather than an argument.
The full writeup carries every trial, the pinned versions and images, the reasoning behind each metric, and the four harness bugs that produced plausible wrong numbers before they were caught.
Every tool gets the same service body and the same probe interval. Where a setting changes a result — stopasgroup, startsecs, exec: — both configurations are charted. Trial counts are 2–5 per figure, cold, with raw output published alongside the scripts.
Gaps: Compose ran against the host daemon while sysg ran in a container, so the boot figure is indicative rather than controlled. systemd is charted on install size only — its runtime rows need a VM. Docker's live-restore: true is untested. N=40 Compose memory is extrapolated from the measured per-container cost.