Repository navigation
feat(network): Control arrival cushion and starting runahead, and start the match in sync - #664
Open
tintinhamans wants to merge 25 commits into
Conversation
…m::openArchiveFile() (TheSuperHackers#3376) (cherry picked from commit 86f2cab)
(cherry picked from commit 5db4f75)
…leSystem, Win32LocalFileSystem (TheSuperHackers#3374) (cherry picked from commit 3f3ed9f)
…ile::getFileInfo(), StdBIGFile::getFileInfo() (TheSuperHackers#3415) (cherry picked from commit b805c12)
…File (TheSuperHackers#3505) Both classes are identical apart from their name and contain no platform specific code. Nothing in them depends on the BIG format either: they open a file from an offset and a size inside the archive file. ArchiveFile takes over their functions and is no longer an abstract class. (cherry picked from commit 52a777a)
…ystem into BIGFileSystem (TheSuperHackers#3505) Both classes are identical apart from their name and go through the local file system for all file access. The one class that remains sits next to ArchiveFileSystem in Core/GameEngine. (cherry picked from commit e4b4d1e)
…e loadBigFilesFromDirectory (TheSuperHackers#3505) loadMods refers to BIG files, which nothing else in ArchiveFileSystem does. It becomes a virtual function that BIGFileSystem implements. loadBigFilesFromDirectory is renamed to loadArchiveFilesFromDirectory, because the base class is not tied to one archive format. (cherry picked from commit f299561)
tintinhamans
force-pushed
the
arctic/go/stack2/09-runahead-controller
branch
from
October 25, 2026 05:20
ede9402 to
a3681d2
Compare
…e Zero Hour archives (cherry picked from commit aaea4c1)
…only with verbose logging
tintinhamans
force-pushed
the
arctic/go/stack2/09-runahead-controller
branch
from
October 25, 2026 11:15
a3681d2 to
e3feda5
Compare
…and forwarded traffic
tintinhamans
force-pushed
the
arctic/go/stack2/09-runahead-controller
branch
from
October 25, 2026 12:54
e3feda5 to
4c5132e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Merge after #663.
A latency formula sizes the run ahead from a round trip, but what stalls the game is whether the commands of the slowest sender arrive before the frame that needs them. The formula also has to guess a start value, and after a loss burst it kept the run ahead high for a long time.
With
input_delay.controller(true) the run ahead follows the arrival cushion instead. Every player reports its lowest cushion per sender with its late commands and stall time, and the packet router sums the two directions of each pair and keepsinput_delay.margin_frames(1) spare per direction. A baseline from a forgetting quantile of the normal windows is raised only for spikes that recur. Withinput_delay.fast_recovery(true) the run ahead falls a third of the excess per step after an isolated spike.input_delay.max_frames(64, retail 128) caps it. A slow producer is left out, an outage holds the run ahead, screenshot capture stalls do not count, and without a complete pair the formula of the previous PR takes over. At match start the router decides the run ahead from every player's lobby round trip, and the load waits for it. The lobby popup also shows the expected input delay.The match start is synchronized on the new
NETWORK_CHANNEL_START. Players send READY at two sync points: on the load screen once loading is done (waiting up to 3 s for the direct path), and after local setup with the load screen still up. The router answers with GO and a per-peer delay from the seed latency (at most 250 ms), each stage times out after 10 s, players that were lost are left out, and it is online only. The stock fade-in from black advances only on logic frames, so a start stall showed a black screen.Wire change: the run ahead metrics message carries the cushion, late count, stall ms and screenshot flag, and the start channel is new. Trade-off: the controller returns to a low run ahead quickly when loss ends, which costs more stall time if loss returns. In the returning-loss rig run the old code stayed at R 56 to 64 and this went back to about 7, but stalled about 30 s of 110 s against 18.7 s. The synchronized start costs about 60 to 80 ms per stage, and relay-only players add up to 3 s.
controllerandfast_recoveryare on by default as in the tester build, and the service can turn them off.Tested: builds x86 Release
z_generals. Rig runs of the full stack, 3 players, 0 CRC mismatches, n=1. On a slow CPU-bound host R stayed at 4 to 5 instead of hitting the old 64 cap. Start sync rig: frame-1 skew went from 1.5 to 2 s down to 6 to 15 ms, no start stalls, the fade takes 0.6 s on both.