-
Notifications
You must be signed in to change notification settings - Fork 0
Storage und Map Streaming
← Home · Zurück: Performance-Guide
Wie der Project-Zomboid-B42-Server die Welt auf die Platte schreibt und
beim Spielen wieder streamt, welche Storage-Tiers in der Praxis sinnvoll
sind, wie man Symptome misst und wann eine tmpfs/RAM-Disk eine Option
ist. Diese Seite ist die deutschsprachige Adaption des englischen
Storage-Guides b42-storage-map-streaming-guide.md aus dem Repo und
übernimmt dessen Mess-Schwellen, Mess-Befehle und tmpfs-Skizze 1:1 mit
Quellen-Label. Repo-Verhalten 1:1 aus dem Repo-Klon.
Label-Legende: (Repo-Default) = Wert/Pfad steht 1:1 im Repo. (Community- Quelle: ...) = extern belegt. (Heuristik) = begründete Eigen-Empfehlung. The Indie Stone (TIS) veröffentlicht keine offiziellen IOPS- oder Latenz-Specs — Vendor-Zahlen sind Marketing, keine B42-Anforderung.
B42 bringt zwei Eigenschaften mit, die den Storage-Druck gegenüber B41 deutlich erhöhen (Heuristik, abgeleitet aus dem EN-Storage-Guide):
- Bis zu 32 Etagen Voxel-Daten pro Chunk — beim Aufzugfahren oder beim Betreten einer Stadt mit Hochhäusern lädt der Server entsprechend mehr Voxel-Slices nach (Heuristik; Symptomlage: Community-Quelle, GTX Gaming).
-
Cell-/Chunk-Streaming + periodische Autosave-Bursts — kontinuierliche
Random-Reads beim Cell-/Loot-/Container-Zugriff, dazu alle
SaveWorldEveryMinutes=15Minuten (Repo-Default ausservertest.ini.tmpl) ein Schreib-Burst (Heuristik, EN-Storage-Guide). - Dichte Basen konzentrieren Lese- und Schreibdruck — mehr Welt- und Container-Zustand wird gemeinsam abgerufen (Heuristik, EN-Storage-Guide).
Konsequenz: Storage ist auf B42 der häufigste Engpass, bevor CPU oder RAM ins Limit gehen (Heuristik, Performance- und Storage-Guide).
Wo der Server welche Daten hält. Pfade 1:1 aus dem Repo-Stand
(Repo-Default, .env.example): die Repo-Defaults lauten /opt/pzserver/...,
nicht /home/pzuser/... wie im EN-Guide. Die Spalte „EN-Guide" zeigt
die pzwiki-Konvention, die der EN-Storage-Guide verwendet — das ist
Community-Wissen, nicht Repo-Stand.
| Zweck | Repo-Pfad (Repo-Default) | EN-Guide-Pfad (Community-Quelle: pzwiki) |
|---|---|---|
| Server-Install (Binaries, StartServer64.sh) |
${PZ_HOME} = /opt/pzserver und ${PZ_SERVER_DIR} = /opt/pzserver/server (Repo-Default) |
/opt/pzserver/ oder steamapps/common/Project Zomboid Dedicated Server/
|
| Konfiguration (INI, SandboxVars, Spawn) |
${PZ_DATA_DIR}/Server/ = /opt/pzserver/Zomboid/Server/ (Repo-Default) |
~/Zomboid/Server/ |
| Multiplayer-Welt + Cell-Saves |
${PZ_DATA_DIR}/Saves/Multiplayer/<world>/ (Repo-Default; Backup-Ziel Nr. 1) |
~/Zomboid/Saves/Multiplayer/<world>/ |
| Spielerbezogene Map-Daten |
${PZ_DATA_DIR}/Saves/ (Repo-Default) |
~/Zomboid/Saves/ |
| Datenbankdateien |
${PZ_DATA_DIR}/db/ (Repo-Default) |
~/Zomboid/db/ |
~ im EN-Guide meint das Home des Server-Kontos; im Repo ist dieses Konto
pzserver (aus PZ_USER=pzserver, .env.example). Beide Quellen
bezeichnen also dasselbe logische Layout, nur an unterschiedlichen Pfaden.
Die folgende Tabelle übernimmt Symptome und Tiers aus dem EN-Storage-Guide und dem PDF-Handbuch (Kapitel 2) 1:1 und behält deren Labels bei (Community-Quelle/Heuristik). Es gibt keine offiziellen TIS-IOPS-Specs — Vendor-Zahlen sind Marketing (Community-Quelle, EN-Storage-Guide).
| Tier | Erwartetes B42-Verhalten | Quelle/Label |
|---|---|---|
| HDD | Dokumentiertes Symptomgebiet: lange Welt-Ladezeiten, stotterndes Cell-Streaming, Rubber-Banding, verzögerte Loot-/Inventar-Interaktion an stark frequentierten Orten | Community-Quelle (Vendor-Angabe GTX Gaming) |
| SATA SSD | Meist brauchbar für kleine Server mit moderater Population und wenigen dichten Basen; kann bei überlastetem Controller dennoch stocken | Heuristik |
| NVMe (Consumer/Enterprise) | Empfohlener Storage-Tier, da der Workload von latenzarmen Random-Reads profitiert | Heuristik |
| NVMe Gen4/Gen5 RAID | Von Hostern für PZ vermarktet; verbessert ggf. Aggregat, begründet aber kein B42-IOPS-Ziel | Community-Quelle (Vendor-Marketing) |
Eine SATA-SSD garantiert nicht automatisch Geschwindigkeit; ein NVMe kann hinter einem überlasteten Controller langsam wirken. Maßgeblich ist die Messung am Gerät, das die Live-Save-Struktur bedient (Heuristik, EN-Storage-Guide).
Dokumentierte Slow-Storage-Symptome (Community-Quelle, GTX Gaming, EN-Storage-Guide):
- Loot-Lag um die 30 Sekunden an großen Basen
- Rubber-Banding an großen Basen
- Scheinbar endloses Laden der Welt beim Verbinden
Wichtig: Dieselbe Beobachtung kann von Spielern als „loot lag", „rubber-banding", „server lag" oder „slow world load" beschrieben werden — die Subsysteme sind oft unterschiedlich verantwortlich. Korrelation mit exaktem Zeitstempel ist Pflicht (Heuristik).
Eine Lag-Beobachtung ist erst dann ein Storage-Verdacht, wenn andere Verursacher ausgeschlossen sind (Heuristik, EN-Storage-Guide). Die folgende Mini-Tabelle hilft bei der Schnelldiagnose:
| Beobachtung | Eher Storage | Eher JVM/GC | Eher Netzwerk |
|---|---|---|---|
await & iowait beide hoch |
ja (Heuristik) | nein | nein |
await hoch, iowait niedrig |
fraglich — eventuell Controller-Konflikt | nein | nein |
| GC-Pausen dominieren Log | nein | ja (Heuristik) | nein |
| Spieler-Desync nur bei einem Client | nein | nein | ja (Heuristik) |
Lag exakt zum Save-Zeitpunkt (SaveWorldEveryMinutes=15) |
ja (Heuristik) | nein | nein |
| Lag beim ersten Betreten einer neuen Zelle | ja (Heuristik) | nein | nein |
Die folgenden Schwellen sind Heuristik (definiert vom EN-Storage-Guide, nicht vendor-dokumentiert und keine offiziellen B42-Anforderungen). Sie sind Startpunkte für die Untersuchung, keine Garantien. Quelle: EN-Storage- Guide und PDF-Handbuch Kapitel 8 (Block 249–253) — Werte 1:1 übernommen.
Metrik (iostat -x / vmstat) |
Gesund | Degradiert | Kritisch | Spielerisch sichtbar |
|---|---|---|---|---|
Device await
|
< 1 ms (Heuristik) |
1–5 ms (Heuristik) |
> 5 ms anhaltend (Heuristik) |
Save-Verzögerung, verzögerte Inventar-/Loot-Interaktion, Stottern |
Device %util
|
< 50 % (Heuristik) |
50–85 % (Heuristik) |
> 85 % anhaltend (Heuristik) |
Queueing, lange Disk-Waits, Stalls bei Save-Bursts |
CPU iowait
|
< 2 % (Heuristik) |
2–10 % (Heuristik) |
> 10 % (Heuristik) |
Pausen und Rubber-Banding, weil CPU auf Storage wartet |
| Save-Burst-Dauer |
< 2 s (Heuristik) |
2–5 s (Heuristik) |
> 5 s (Heuristik) |
Rubber-Banding während Autosaves; lange Bursts überdauern UI-Latenz |
Auswertungslogik (Heuristik, EN-Storage-Guide):
-
awaitimmer mit%util, Queue-Tiefe und Durchsatz lesen; ein schnelles Gerät kann beschäftigt aussehen, ein langsames Bursts zeigen. - Hoher
iowait+ hoherawait= stärkerer Storage-Verdacht als jeder Einzelwert. Beide gesund → JVM/GC, Zombie-Dichte, Netzwerk prüfen. - Save-Bursts im selben Intervall messen, in dem Spieler Lag melden; wiederholbare Muster schlagen Einzelspitzen.
- Mehrere Sessions vergleichen; ein einzelner Ausschlag kann ein konkurrierender Prozess auf demselben Gerät sein.
Alle Befehle 1:1 aus dem EN-Storage-Guide. Werkzeuge stammen aus dem Paket
sysstat (Debian/Ubuntu: apt install sysstat).
| Befehl | Zweck |
|---|---|
iostat -x 2 |
Gerät-Latenz, %util, Queue-Tiefe, Durchsatz alle 2 Sekunden |
pidstat -d -p $(pgrep -fi zomboid) 2 |
Disk-Aktivität des Java-/Launcher-Prozesses |
vmstat 2 |
wa (iowait), Run-Queue, Swap-Druck, Speicher |
pidstat -t 2 |
Threads — der heiße Simulationskern |
df -h ${PZ_DATA_DIR}/Saves/Multiplayer |
Filesystem der Live-Save-Struktur; bei tmpfs: tmpfs-Mount |
du -sh ${PZ_DATA_DIR}/Saves/Multiplayer/<world> |
Weltengröße vor tmpfs-Dimensionierung |
findmnt -T ${PZ_DATA_DIR}/Saves/Multiplayer |
Mount-Quelle und Optionen für den Save-Pfad |
rsync -an --delete -- <tmpfs-world>/ <durable-mirror>/ |
Trockenlauf des Sync-Back (zeigt nur, was geändert würde) |
systemctl list-timers 'pz-*' |
Prüft aktive tmpfs-Sync-Timer |
Findet pgrep -fi zomboid mehrere Prozesse, die tatsächliche Java-PID
direkt an pidstat -d -p PID 2 übergeben (Heuristik, EN-Storage-Guide).
Die folgende Reihenfolge übernimmt die Eskalationsstufen aus dem PDF- Handbuch Kapitel 2 und dem EN-Storage-Guide 1:1 (Heuristik). Pro Messzyklus immer nur eine Stufe anwenden.
-
Platzierung verifizieren: Liegen Welt, Java-Prozess und Swap auf
dem vorgesehenen Gerät? (Repo-Pfad:
${PZ_DATA_DIR}=/opt/pzserver/Zomboid, Repo-Default.) -
Beweise zeitlich zuordnen: Lag-Reports mit Save-Burst-Zeitpunkten
(
SaveWorldEveryMinutes=15, Repo-Default), Connect-Versuchen und Besuchen lang ungesehener Zellen korrelieren. -
Konkurrenz reduzieren: Backups, Paket-Caches und Bulk-Jobs vom
Save-Gerät weg oder außerhalb der Peak-Zeiten legen. Das Repo-Backup
läuft um 04:00 (
zomboid-backup.timer, Persistent, Repo-Default); wer nachts spielt, verschiebt den Zeitpunkt. - Storage eskalieren: Welt auf NVMe ziehen; tmpfs erst nach den Stufen 1–3.
- Gameplay/Compute eskalieren: Sind Latenzen gesund, Zombie-Dichte, Population, JVM, CPU und Netzwerk prüfen.
Vor dem ersten Hebel folgende Befehle laufen lassen (Heuristik, EN- Storage-Guide; Repo-Pfad-Defaults):
df -h ${PZ_DATA_DIR}/Saves/Multiplayer
du -sh ${PZ_DATA_DIR}/Saves/Multiplayer/<world>
iostat -x 2 | tee /tmp/iostat-pre.log
# danach Last auslösen (z. B. Spieler betritt neue Zelle),
# iostat beobachten und Log mit "iostat-pre.log" vergleichen.So lässt sich später objektiv zeigen, ob die Eskalationsstufe tatsächlich geholfen hat — sonst bleibt „gefühlt besser" als einziger Beleg.
Wichtig (Repo-Stand): Das Repo liefert kein tmpfs-Setup. Alles in diesem Abschnitt ist ein optionaler Ausbau auf Basis des EN-Storage- Guides (Standard-Linux-tmpfs+rsync, keine TIS-Empfehlung; Heuristik). Wer den Standard-Repo-Pfad nicht verlassen will, überspringt diesen Abschnitt und bleibt auf dauerhaftem Storage unter
${PZ_DATA_DIR}(Repo-Default).
- Live-Weltbaum auf tmpfs legen — der Pfad
${PZ_DATA_DIR}/Saves/Multiplayer(Repo-Default) ist das primäre Backup-Ziel, also auch der erste tmpfs-Kandidat. - Installation auf dauerhafter Platte lassen — Binaries und Java-Runtime sind read-mostly und werden ohnehin vom Linux-Page-Cache bedient.
- Optional auch
${PZ_DATA_DIR}/Saveskomplett, falls der größere Footprint gerechtfertigt ist — Pfad-Muster analog (Heuristik).
Aktuelle Größe messen (Heuristik):
du -sh ${PZ_DATA_DIR}/Saves/MultiplayerFaustregel: aktuelle Größe × 1,5 (Heuristik, EN-Storage-Guide). Niemals
tmpfs größer wählen als: physisches RAM - JVM-Heap - 8 GB OS-Reserve - Sicherheitsmarge für andere Dienste (Heuristik, EN-Storage-Guide). Auf
einem 24-GB-Host mit 12G Heap bleibt für tmpfs entsprechend wenig Luft
— die Heap-Tier-Rechnung aus Hardware-Empfehlungen ist vorrangig.
Repo-Pfade übernehmen (Heuristik, abweichend vom EN-Standardbeispiel):
# Beispiel: tmpfs auf /opt/pzserver/Zomboid/Saves/Multiplayer
# Pfad 1:1 aus .env.example: PZ_DATA_DIR=/opt/pzserver/Zomboid
# uid/gid des Server-Kontos einsetzen (default: pzserver)
tmpfs /opt/pzserver/Zomboid/Saves/Multiplayer tmpfs rw,nosuid,noexec,size=20G,uid=<UID>,gid=<GID>,mode=0750 0 0
UID/GID des Server-Kontos prüfen: id pzserver (Heuristik). uid=<UID>
muss numerisch sein — Namen werden vom Mount-Helper nicht aufgelöst
(EN-Storage-Guide).
Vor dem ersten Mount (Heuristik, EN-Storage-Guide):
sudo systemctl stop zomboid
sudo install -d -o pzserver -g pzserver /opt/pzserver/Zomboid/Saves/Multiplayer
# Dauerhafter Spiegel — Repo-Stand kennt diesen Pfad NICHT,
# eigene Konvention auserhalb des Repos:
sudo install -d -o pzserver -g pzserver /opt/pzserver-backup/Saves/Multiplayer
rsync -a --delete /opt/pzserver/Zomboid/Saves/Multiplayer/ /opt/pzserver-backup/Saves/Multiplayer/
sudo systemctl daemon-reload
sudo mount /opt/pzserver/Zomboid/Saves/MultiplayerOhne Seed ist das tmpfs beim ersten Boot leer — der Server startet ohne Welt (Heuristik, EN-Storage-Guide).
# /etc/systemd/system/pz-ramdisk-seed.service
[Unit]
Description=Seed Project Zomboid multiplayer saves from durable storage
Wants=local-fs.target
After=local-fs.target
RequiresMountsFor=/opt/pzserver/Zomboid/Saves/Multiplayer
[Service]
Type=oneshot
User=pzserver
Group=pzserver
TimeoutStartSec=30min
ExecStart=/usr/bin/rsync -a --delete -- /opt/pzserver-backup/Saves/Multiplayer/ /opt/pzserver/Zomboid/Saves/Multiplayer/
[Install]
WantedBy=multi-user.targetLiegt außerhalb des Repo-Stands (Heuristik, EN-Storage-Guide): Repo liefert keine eigene Service-Datei; die obigen Units entstehen manuell in
/etc/systemd/system/.
Der Sync-Back-Timer im EN-Storage-Guide läuft alle 5 Minuten; das ist eine
administrative Wahl, kein TIS-Intervall. Mit Persistent=true auf dem Timer
kann ein Catch-up-Lauf beim Boot den rsync---delete gegen ein leeres
tmpfs feuern und den dauerhaften Spiegel leeren — das Requires/
After=pz-ramdisk-seed.service im Service schützt daraus nur, wenn der
Timer regulär zieht (Heuristik, EN-Storage-Guide).
# /etc/systemd/system/pz-ramdisk-sync.timer
[Unit]
Description=Periodically back up the Project Zomboid tmpfs world
[Timer]
OnCalendar=*-*-* *:0/5:00
Persistent=true
RandomizedDelaySec=30s
Unit=pz-ramdisk-sync.service
[Install]
WantedBy=timers.targetDer Repo-zomboid.service enthält keinen ExecStop-rsync
(Repo-Stand, 1:1 aus systemd/zomboid.service). Wer tmpfs nutzt, ergänzt
den Service um eine ExecStop=--Zeile, damit ein sauberer Stop die
Welt noch synchronisiert, bevor der Prozess endet:
# /etc/systemd/system/zomboid.service (Erweiterung)
[Service]
ExecStop=/usr/bin/rsync -a --delete -- /opt/pzserver/Zomboid/Saves/Multiplayer/ /opt/pzserver-backup/Saves/Multiplayer/ProtectSystem=strict und andere Sandboxing-Direktiven nicht ohne Test
hinzufügen — sie können den tmpfs-Pfad oder den Spiegel-Pfad
unerwartet abschneiden (Heuristik, EN-Storage-Guide).
Hinweis (Community-Quelle: pzwiki): Die Entwickler raten von direkter systemd-Invocation wegen der SIGTERM-Behandlung ab; das Repo startet trotzdem per systemd mit sauberem
/quit-Pfad über die Stop-Skripte — siehe systemd-Referenz.
- Eine RAM-Disk ist kein Backup (Heuristik, EN-Storage-Guide).
- Kernel-Panic, Host-Crash oder Stromausfall verlieren alles seit dem
letzten erfolgreichen Sync;
ExecStop-rsync läuft nach plötzlichem Stromausfall nicht. - Backup-Ziel darf nie auf dem tmpfs selbst liegen — der Spiegel auf dauerhaftem Storage ist nur eine Arbeitskopie, keine Historie.
- Timer- und
ExecStop-rsyncs können den Weltbaum mitten im Save erwischen; im Zweifel das letzte Backup bevorzugen, nicht den Spiegel (Heuristik, EN-Storage-Guide). - Restore testen: Server stoppen, Live-Kopie zur Seite legen, aus Backup zurückladen, tmpfs neu seeden, Welt laden — erst dann in Produktion vertrauen.
- Wenn der Sync-Service ausfällt, bleibt Storage flüchtig; eine spätere erfolgreiche Sync kopiert den aktuellen tmpfs-Inhalt — sie rekonstruiert bereits verlorene Daten nicht (Heuristik).
- Host hat nicht genug RAM für JVM-Heap, Live-Saves und OS-Reserve.
- Kleiner Host mit Multi-GB-Welten — Kapazitätslimit und Java-Speicher konkurrieren.
- Erst NVMe evaluieren; tmpfs nur bei großer RAM-Reserve als zusätzliches Experiment (Heuristik, EN-Storage-Guide).
Die drei Sandbox-Werte Respawn Hours, Respawn Unseen Hours und
Respawn Multiplier (pzwiki-Sandbox, dokumentiert im EN-Storage-Guide
Kapitel 4) steuern, wann und wie viel Zombie-Respawn stattfindet.
Wichtig (Community-Quelle, EN-Storage-Guide): Die exakte camelCase-
Lua-Schreibweise ist nicht zweifelsfrei verifiziert — über das
In-Game-Sandbox-UI oder den servertest_SandboxVars.lua-Editor setzen,
nicht durch geratene Key-Namen. Das Repo-Preset coop-balanced.lua setzt
RespawnHours=0 (Repo-Default; aus = kein Respawn = keine Respawn-
Berechnung, siehe Server-Konfiguration).
Wenn Spieler in lang ungesehene Gebiete vorstoßen, lädt der Server Population, Loot, Container und Fahrzeug-Zustand aus dem Storage — ein Read-/Write-Burst folgt. Bei hoher Storage-Latenz wird das als Loot-Lag, Inventory-Delay oder Loading-Delay spürbar (Heuristik, EN-Storage-Guide).
Beim Host-Wechsel von B41 auf B42 kann beim Start
Assertion Failed: Illegal termination of worker thread auftreten
(Community-Quelle: pzwiki). Reparatur (Community-Quelle: pzwiki):
-
steam_appid.txtmit Inhalt108600im Server-Verzeichnis anlegen. - Alle Serverprozesse sauber stoppen.
-
.ini,.lua,Zomboid- und Save-Verzeichnisse sichern. - Bestehenden
Zomboid-Ordner entfernen, damit B42 ihn neu erzeugen kann. - Nur als kompatibel bekannte Konfiguration und Welt zurückladen.
- Ohne B42-Beta-Flag starten und ersten Save-Zyklus beobachten.
Details: Troubleshooting. Den Save-Baum nicht ohne verifiziertes Backup löschen.
- HDD-Symptome sind real, aber kein TIS-Muss — sie stammen aus Vendor- Beobachtungen (Community-Quelle).
- NVMe ist der empfohlene Tier, gemessen am Gerät unter
${PZ_DATA_DIR}/Saves/Multiplayer(Heuristik). - tmpfs ist ein Repo-externes Experiment für Hosts mit großer RAM-Reserve (Heuristik); ohne Backup ist es wertlos.
- Immer nur eine Schraube gleichzeitig drehen; Korrelation zwischen Lag- Report und Save-Zeitpunkt ist Pflicht (Heuristik).
Weiter: Performance-Guide · Hardware-Empfehlungen · Backup-und-Restore · Troubleshooting
Vertieft in Repo: pz-b42-server-guides/b42-storage-map-streaming-guide.md
und docs/09-performance.md.
Labels: Community-Quelle = extern belegt (Herkunft in Klammern, z. B. pzwiki, Steam-Diskussionen, GCP-Preisliste) · Repo-Default = steht genau so im Repo (Template, Skript oder .env.example) · Heuristik = begründete Empfehlung dieses Projekts, nicht extern verifiziert.
The Indie Stone (TIS) publiziert keine offiziellen Storage-/IOPS-/Performance-Specs — Zahlen in diesem Wiki nie als TIS-Anforderung lesen.
Inhalte zielen auf den B42-Stable-Branch: seit B42.20 der Default-Zweig in Steam, kein -beta-Opt-in nötig (Community-Quelle).
Details zu Labels, Quellen und Redaktionsregeln: Konventionen-und-Quellen.
Einstieg
Referenz
- Makefile-Referenz
- Cheatsheet-Tagesbetrieb
- ENV-Variablen
- Server-Konfiguration
- Admin-Befehle
- Mods-Referenz
- Spawn-System
- Skripte-Referenz
- systemd-Referenz
- Ports-und-Netzwerk
- SteamCMD-Referenz
Betrieb
- Wartung-und-Automatik
- Backup-und-Restore
- Updates-und-Rollback
- Monitoring-und-Alerts
- Sicherheit-und-Hardening
- Docker-Betrieb
- GCP-Failover
Tiefenwissen
- Modding-Workflow
- Performance-Guide
- Storage-und-Map-Streaming
- Hardware-Empfehlungen
- Troubleshooting
- Runbook-Raven-Creek
Meta