systemg

Search docs

/
Install

Benchmarks

Aug 21, 2026

How systemg compares

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 is also the only one of the three that leaves nothing running after you stop a service, and the only one that neither duplicates nor loses your workload when the supervisor itself dies.

Full results & methodologyInstall sysg

1.49

s

install to first supervised service

6.91

s

ten-service graph cold boot

12.4

MB

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

sysg

1.49s

Supervisor

5.53s

Docker Compose

15.85s+

seconds, cold

pulled over the network

sysg

6.8 MB

Supervisor

48.0 MB

Docker Compose

172.5 MB

megabytes, cold cache

installed on disk

systemd

14.6 MB

sysg

19.5 MB

Supervisor

26.8 MB

Docker Compose

278.6 MB

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.

how this was measured →

Dependency graph

Ten services, five levels deep

Two independent roots, a five-wide fan-in. 0.64 walked the topological order one unit at a time; 0.65 dispatches every unit whose dependencies are already satisfied.

sysg 0.64.4 — one at a time

14.00s

13.83s

db

queue

cache

ingest1

ingest2

worker1

worker2

worker3

aggregator

reporter

0s

2s

4s

6s

8s

10s

12s

14s

10 steps

sysg 0.65.0 — by dependency level

14.00s

6.91s

db

queue

cache

ingest1

ingest2

worker1

worker2

worker3

aggregator

reporter

0s

2s

4s

6s

8s

10s

12s

14s

5 waves

Each bar is one service becoming ready. Playhead is wall-clock.

2.00×

faster than sysg 0.64.4

sysg 0.65.0

6.91s

Docker Compose

8.31s

1.20× slower

sysg 0.64.4

13.83s

2.00× slower

Supervisor

cannot express this graph

all four, one clock

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.

how this was measured →

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.

sysg

0.00s

health probe

Supervisor, tuned

0.00s

startsecs=5, matched to startup

Compose

−0.52s

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.

how this was measured →

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.

sysg

12.4 MB

Supervisor

18.1 MB

Docker Compose

354 MB

area ∝ MB

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.

how this was measured →

Scaling

Cost per service, as services are added

The intercept matters less than the slope. sysg 0.66 adds an exec: argv form that runs a service directly instead of through a shell, which removes a resident process per service.

0

8

16

24

32

crosses at N≈395

sysg exec:

29.5 MB

Supervisor

28.0 MB

sysg command:

84.7 MB

0

100

200

300

400

500

MB overhead

services supervised → · N=500

drawn to N=500

Fitted from N = 1, 10, 40. Drawn to N = 500.

added MB per service

Supervisor

0.020

sysg exec:

0.035

sysg command:

0.145

fitted slope

processes at N=40

sysg exec:

45

Supervisor

45

sysg command:

85

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.

how this was measured →

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.

sysg

none left

session teardown reaches the setsid child

Docker Compose

none left

container PID namespace collapses

Supervisor, tuned

2 left

stopasgroup + killasgroup; setsid child escaped the group

Supervisor, default

5 left

signals only the pid it spawned

stop →

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.

how this was measured →

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

kill -9 → restart

Docker tested at its default live-restore: false.

sysg

Supervisor

Compose

services survive

yes

yes

no

visible while down

yes

yes

no

no duplicate started

yes

no

yes

workload kept

yes

yes

no

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.

how this was measured →

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

installs without root

systemd was measured on install size only; its runtime rows need a machine where it is PID 1.

how this was measured →

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.

Method

Check any of it

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.

how this was measured →