sceNetAdhoc: Relay without fixed real-time waits

aemu_postoffice is now at upstream main, which has the relay performance
fixes: the built-in relay server waits for traffic and pumps as soon as
it arrives instead of sleeping 1 ms between pumps, and pumps on its own
thread instead of waking three workers twice each per pump; closing a
session no longer sleeps 50 ms (the delay is now an option, 0 here,
where everything but a PTP connect's thread, which is joined before its
session closes, runs on the CPU thread); connects and blocking waits for
the server's replies wait on the socket instead of sleeping or spinning.
Unread PTP data is also delivered before a close now.

The pair tests through the relay used to barely gain from speed (29 s at
600%, 22 s at 1600%); now 19 s and 11 s, as fast as P2P at 600%.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-10-31 12:01:20 +01:00
1 parent c0e750726f
commit 6079a8264f
2 files changed
+11 -7

No files matched your search

+10 -6
View File
@@ -1442,6 +1442,10 @@ static void SetupAdhocRelayMode() {
netAdhocRelayModeEnetPdpReliable = g_Config.bAdhocRelayModeEnetPdpReliable;
init_aemu_postoffice(netAdhocUseUdp);
// Closing a session normally first sleeps 50 ms, in case another thread is about to use it. Here
// everything but a PTP connect's own thread runs on the CPU thread, and that thread is joined
// before its session is closed.
set_close_delay_aemu_postoffice(0);
if (netAdhocUseUdp) {
aemuPostofficeEnetPumping = true;
@@ -1735,8 +1739,9 @@ void __NetAdhocInit() {
* from ppsspp's adhocctl server
*/
config.strict_mode = false;
// One worker per pool is plenty for a server that sees a handful of players.
config.num_threads = 1;
// No worker threads: for a server that sees a handful of players, pumping on this thread
// beats waking workers several times per pump.
config.num_threads = 0;
// The port the relay client connects to.
config.port = AEMU_POSTOFFICE_PORT;
@@ -1752,14 +1757,13 @@ void __NetAdhocInit() {
INFO_LOG(Log::sceNet, "RelayServer: Listening for Connections on TCP Port %u", config.port);
while (adhocServerRunning) {
auto start = std::chrono::steady_clock::now();
auto pump_status = relay_server.pump();
if (pump_status == aemu_postoffice_server::ServerPumpStatus::LISTEN_SOCK_DEAD) {
break;
}
// Every hop through the relay waits for the next pump, so keep them close together. Idle
// (nobody connected) too, since that's when a game's first connection comes in.
std::this_thread::sleep_until(start + std::chrono::milliseconds(1));
// Pump again as soon as something arrives, so a message is relayed at once. The timeout
// only bounds how long it takes to notice adhocServerRunning going false.
relay_server.wait(10);
}
INFO_LOG(Log::sceNet, "RelayServer: Shutdown complete");