Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Hermod
Compresses about two thirds of a dedicated server's outgoing traffic away, makes the ZDO send budget adjustable, and measures where the server's time actually goes. Compression needs the mod on each player too.
By GBV
| Date uploaded | 2 weeks ago |
| Version | 0.1.4 |
| Download link | GBV-Hermod-0.1.4.zip |
| Downloads | 33 |
| Dependency string | GBV-Hermod-0.1.4 |
This mod requires the following mods to function
denikson-BepInExPack_Valheim
BepInEx pack for Valheim. Preconfigured with the correct entry point for mods and preferred defaults for the community.
Preferred version: 5.4.2350README
Hermod
Performance and networking for Valheim dedicated servers. It changes no gameplay.
Hermod cuts the server's outgoing traffic by about two thirds, opens up two limits the game leaves fixed, and keeps a record of where the server's time actually goes so a slowdown can be diagnosed rather than guessed at.
What It Does
Compresses network traffic. On a real server 8.6 MB of outgoing traffic became 3.0 MB, with no change to frame time or CPU. Every player needs the mod for this part; a player without it just exchanges ordinary packets.
Raises the limit on world data per player. The game stops sending a player world updates once a fixed amount is in flight to them, which bites hardest on players furthest from the server. That limit is adjustable.
Limits time spent building new terrain. Generating a zone with a crypt or a village in it is the single most expensive thing a server does, and several can land in the same tick when people explore in different directions. The budget spreads them out.
Improves the Steam connection settings. The game pins its send rate to a fixed value and never disables Nagle batching. Hermod raises the ceiling and turns the batching off, and only ever in the direction that helps.
Records what the server is doing. One row a minute to a spreadsheet: frame times, memory, object counts, per-player bandwidth and update rate, compression, terrain generation and saves. Most of it needs no hooks into the game, so it keeps working after a Valheim update.
Watches for portal ghosts. A copy of a player left standing at a portal they walked through gets reported by name. It only watches; nothing about portals behaves differently.
Does not cap the frame rate. A Valheim server sends updates to one player per frame, so capping the frame rate makes things worse for everyone. Hermod leaves it alone and refuses a cap that would slow updates below ten a second.
Installing
Install it on the server. Install it on players too if you want compression, which is the one part that needs both ends.
The commands need it on the client you type them from, because a Valheim dedicated server has no console of its own. Commands travel to the server and are checked for admin rights first.
A crossplay server gets the measurement but not the networking. Compression and the Steam settings both need a Steam connection, which a crossplay server never makes. Hermod says which kind of connection it opened in the log at startup.
What It Writes
Three files in BepInEx/config/, and a short summary to the log every few minutes.
| File | Contents |
|---|---|
gbv.valheim.hermod.session.csv |
One row a minute: frame times, CPU, memory, object counts, send rates, compression, terrain generation, saves |
gbv.valheim.hermod.peers.csv |
One row a minute per player: ping, link quality, bandwidth, queue depth, update rate |
gbv.valheim.hermod.report.json |
The session, with the worst frames and slowest zones timestamped |
Four columns answer most questions: ms_p99 is what a bad frame looks like, frames_gt100 is
how often the server actually hitched, gc_stall_ms is how much of the minute went to garbage
collection, and slow_unexplained is slow frames Hermod cannot account for at all.
Percentile columns are bucket edges, so ms_p99 = 16.7 means 99% of frames were at or below
16.7 ms. The _max columns are exact.
Every column is explained in wiki/Reading-The-Session-Log.md.
Commands
Typed from an admin's client.
| Command | What it does |
|---|---|
hermod_status |
Frame time, CPU, object counts, compression and send rate right now |
hermod_peers |
Per player: ping, queue depth, how often they are updated |
hermod_mark <label> |
Stamp a labelled boundary into the logs, for comparing before and after |
hermod_profile <vanilla|tier1|relay> |
Flip the whole set of settings at once, live |
hermod_compress <on|off|status> |
Packet compression. Applies immediately for everyone connected |
hermod_queue <bytes|off|status> |
The per-player limit on world data in flight |
hermod_relay <on|off|status> |
The update rewrite described under Settings |
hermod_net [apply] |
Show the Steam settings in force; apply re-asserts them on live connections |
hermod_fps <n|auto|off> |
Cap the frame rate, with the refusal described above |
hermod_probe <on|off> |
The detailed timings, leaving the rest of the measurement running |
hermod_report |
Write the report now |
hermod_reload |
Re-read the settings file |
hermod_save |
Write the settings currently in force back to the file |
hermod_panic |
Put everything back the way the game had it, immediately |
Settings
BepInEx/config/gbv.valheim.hermod.json. Enabled and MeasureOnly are in the BepInEx config
instead, so the mod can be switched off without editing JSON.
| Setting | Default | What it does |
|---|---|---|
compressionEnabled |
on | Packet compression. Needs the mod on both ends |
compressionLevel |
1 | 1 to 9. Higher buys a few percent for several times the CPU |
inFlightCeiling |
0 | The per-player limit on world data in flight. 0 keeps the game's own |
zoneGenBudgetMs |
50 | Milliseconds of each tick that may go into building terrain. 0 removes the limit |
applySteamSettings |
on | Master switch for the connection settings |
nagleTimeMicros |
0 | Steam's batching delay. 0 disables it, -1 leaves it alone |
sendRateMin |
153600 | Left at the game's own value |
sendRateMax |
1048576 | The ceiling Steam is allowed to reach |
sendBufferSize |
0 | Leaves Steam's default alone |
maxTotalUploadKiBPerSec |
0 | Your upload budget, divided between the player slots |
targetFrameRate |
0 | 0 auto, -1 uncapped, or a number. Auto means do not cap |
relayEnabled |
off | Sends updates to every player on a timer rather than one per frame. Helps most when players have real latency; test before leaving it on |
relayTargetHz |
20 | Passes per second the relay aims for |
relayFrameRateCap |
60 | The cap auto chooses once the relay is running |
relayAbortFrameMs |
250 | How bad frame times must get before the relay turns itself off |
fixZdoExtraDataLeak |
off | Closes a memory leak in the game itself. Watch extradata_ratio in the log with it off, then on |
probesEnabled |
on | The detailed timings |
reportMinutes |
5 | How often the report and the log summary are written |
slowFrameMs |
100 | A frame worse than this is kept in the report |
slowZoneGenMs |
50 | A zone slower than this is kept, with its coordinates |
writeCsv |
on | Write the two spreadsheets |
writeJson |
on | Write the report |
csvMaxBytes |
8388608 | Rotate the spreadsheets past this size |
deferToOtherNetworkMods |
on | Stand down if another networking mod is installed |
betterNetworkingGuid |
DIT.BetterNetworking10 |
Which mod to stand down for |
A settings file that will not parse leaves whatever was already in force alone, rather than reading as empty.
Running Alongside Other Mods
Run one networking mod, not two. If Hermod finds another it stands down from compression, the send rate, the batching delay and the relay, says so in the log, and carries on measuring. Two mods rewriting the same packets would corrupt traffic rather than fail cleanly, which is why this is automatic.
If a Valheim update moves something Hermod depends on, it names it in the log and carries on
with everything else. Reading the log for Hermod: once after an update is worth doing.
Credits
Built for Guys Being Vikings.
Packet compression is adapted from CW-Jesse's BetterNetworking, by way of LabodiDavid's
Valheim 1.0 fork, under the MIT licence, including the compression dictionary trained on real
Valheim traffic. Full notice in THIRD-PARTY-NOTICES.md, licence in
LICENSE-BetterNetworking.txt.
Zstandard comes from ZstdSharp.Port by Oleg Stepanischev.
CHANGELOG
Changelog
0.1.5
Fixed
- Commands that change a setting now say the change is live only and name
hermod_save. Setting the send budget on a running server and losing it to the next restart, with nothing having warned you, is what prompted this hermod_queueno longer says "no restart needed", which was true about when the change applies and read as "this is saved"
Changed
- The portal ghost detector reports stale records as information rather than warning about a
bug. It was firing on players simply walking away from each other, over a thousand times a
session, claiming an object was left standing when nothing was. The count stays in the
ghostscolumn
0.1.4
Diagnostics only. Nothing about how the server runs has changed.
Added
- Slow frames now say whether the garbage collector was running during them. New
gc_frames,slow_gc,slow_unexplainedandgc_stall_mscolumns, and the worst-frame list in the report tags themgcinstead of leaving the cause blank - A breakdown of what is being destroyed, by prefab, in
dead_createdanddead_top. The session log already counted dead objects; this says what they were
Notes
gc_stall_msis milliseconds out of the 60,000 in a minute, so it reads directly as how much of the server the collector tookslow_unexplainedcounts slow frames with no collection and nothing Hermod instruments running. If that is the large number, the time is going somewhere this mod cannot see: another mod's update loop, or the engine itself- Valheim's Mono runs a non-generational collector, so
gc0,gc1andgc2are the same number printed three times and every collection walks the whole heap. Do not read them as a generational breakdown
0.1.3
Added
- A portal ghost detector. It reports anyone left standing at a portal they walked through,
by name, and counts it in a
ghostscolumn. It does not fix them fixZdoExtraDataLeak, off by default, for a leak in the game itself. Objects near a player who has not received them yet are mistaken for save copies and never freed- A log line at startup saying which backend the server opened on
Changed
- Compression needs 0.1.3 on both ends. A player on 0.1.2 is not broken, they just exchange uncompressed packets
Notes
- A
ghostscolumn that stays at zero means your server does not have the problem. The log line also says how many players it is watching, so a zero is not the same as not looking - Watch
extradata_ratiobefore and after turning the leak fix on. It will not fall, it should stop climbing - Compression and the Steam settings do nothing on a crossplay server, because they live on a Steam socket a PlayFab server never creates. That is what the backend line is for
0.1.2
First release.
Added
- Packet compression. 8.6 MB of outgoing traffic became 3.0 MB on a real server, with no measurable change to frame time or CPU. Needs the mod on both ends
- An adjustable limit on world data in flight per player. The game's own limit tightens with distance, so it bites hardest on the players furthest away
- A budget for time spent building terrain, so several zones landing in one tick cannot stall the server
- Nagle batching off and the Steam send rate ceiling raised, only ever in the direction that helps
- A per-minute record to CSV: frame times, CPU, memory, object counts, per-player ping, bandwidth and update rate, compression, terrain generation and saves
- An update rewrite that sends to every player on a timer rather than one per frame. Off by default
hermod_panic, which reverts every change in one command with players still connected
Notes
- The frame rate is deliberately left uncapped. A Valheim server sends updates to one player per frame, so capping it would cut every player's update rate. A cap that would push delivery below ten a second is refused
- Commands are typed from a client that has the mod, because a Valheim dedicated server has no console of its own
- Crossplay servers get the measurement but not compression or the Steam settings
- Run one networking mod, not two. If another is detected this one stands down from everything that overlaps and says so in the log