From 7193163488b4ce875ce7e6b2accd8daf587d1b5f Mon Sep 17 00:00:00 2001 From: mwiegand Date: Sat, 9 May 2026 09:44:12 +0200 Subject: [PATCH] feat(deploy): perf-baseline directives on left4me-server@.service Slice=l4d2-game.slice, Nice=-5, IOSchedulingClass=best-effort, OOMScoreAdjust=-200, MemoryHigh=1.5G, MemoryMax=2G, TasksMax=256, LimitNOFILE=65536, KillSignal=SIGINT, TimeoutStopSec=15s, LogRateLimitIntervalSec=0. Spec: docs/superpowers/specs/2026-05-09-l4d2-server-host-perf-baseline-design.md --- .../systemd/system/left4me-server@.service | 16 +++++++++ deploy/tests/test_deploy_artifacts.py | 35 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/deploy/files/usr/local/lib/systemd/system/left4me-server@.service b/deploy/files/usr/local/lib/systemd/system/left4me-server@.service index b0e3997..e7414bd 100644 --- a/deploy/files/usr/local/lib/systemd/system/left4me-server@.service +++ b/deploy/files/usr/local/lib/systemd/system/left4me-server@.service @@ -13,6 +13,22 @@ WorkingDirectory=/var/lib/left4me/runtime/%i/merged/left4dead2 ExecStart=/var/lib/left4me/installation/srcds_run -game left4dead2 +hostport ${L4D2_PORT} $L4D2_ARGS Restart=on-failure RestartSec=5 + +# Resource control baseline — see docs/superpowers/specs/2026-05-09-l4d2-server-host-perf-baseline-design.md +Slice=l4d2-game.slice +Nice=-5 +IOSchedulingClass=best-effort +IOSchedulingPriority=4 +OOMScoreAdjust=-200 +MemoryHigh=1.5G +MemoryMax=2G +TasksMax=256 +LimitNOFILE=65536 +KillSignal=SIGINT +TimeoutStopSec=15s +LogRateLimitIntervalSec=0 + +# Hardening (unchanged from previous baseline). NoNewPrivileges=true PrivateTmp=true PrivateDevices=true diff --git a/deploy/tests/test_deploy_artifacts.py b/deploy/tests/test_deploy_artifacts.py index f3f739c..20ef2ce 100644 --- a/deploy/tests/test_deploy_artifacts.py +++ b/deploy/tests/test_deploy_artifacts.py @@ -75,6 +75,41 @@ def test_server_unit_contains_required_runtime_contract(): assert "LockPersonality=true" in unit +def test_server_unit_contains_perf_baseline_directives(): + unit = SERVER_UNIT.read_text() + + # Slice membership. + assert "Slice=l4d2-game.slice" in unit + + # CFS priority bump (no SCHED_FIFO). + assert "Nice=-5" in unit + assert "CPUSchedulingPolicy=" not in unit + + # I/O priority. + assert "IOSchedulingClass=best-effort" in unit + assert "IOSchedulingPriority=4" in unit + + # OOM ordering: game servers survive, sandbox dies first. + assert "OOMScoreAdjust=-200" in unit + + # Memory caps with headroom for map-load spikes. + assert "MemoryHigh=1.5G" in unit + assert "MemoryMax=2G" in unit + + # Bounded fork surface. + assert "TasksMax=256" in unit + + # Plenty of fds for plugin-heavy setups. + assert "LimitNOFILE=65536" in unit + + # srcds clean shutdown via SIGINT, with time to flush. + assert "KillSignal=SIGINT" in unit + assert "TimeoutStopSec=15s" in unit + + # Per-unit override of journald rate limiting (default drops srcds output). + assert "LogRateLimitIntervalSec=0" in unit + + def _fake_command(tmp_path, command_name): marker = tmp_path / f"{command_name}.args" command = tmp_path / command_name