Skip to content

Commit

Permalink
Use the <1ms left over server-step sleep time in next step
Browse files Browse the repository at this point in the history
  • Loading branch information
Desour committed Oct 24, 2024
1 parent 9f43018 commit a199672
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 9 deletions.
29 changes: 21 additions & 8 deletions src/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,12 @@ void *ServerThread::run()
}
framemarker.end();

// how long the last step took, in seconds
float dtime = 0.0f;
// If there's no server lag and packet handling doesn't take too long,
// Server::Receive() waits a bit less than its timeout. We use the remaining
// time to get an average dtime of step_settings.steplen.
float last_remaining_time = 0.0f;

while (!stopRequested()) {
framemarker.start();
Expand All @@ -147,14 +152,19 @@ void *ServerThread::run()

try {
// see explanation inside
if (dtime > step_settings.steplen)
// (+1 ms, because we don't sleep more fine grained)
if (dtime > step_settings.steplen + 0.001f)
m_server->yieldToOtherThreads(dtime);

m_server->AsyncRunStep(step_settings.pause ? 0.0f : dtime);

const float remaining_time = step_settings.steplen
const float this_target_steplen = step_settings.steplen +
last_remaining_time;
float remaining_time = this_target_steplen
- 1e-6f * (porting::getTimeUs() - t0);
m_server->Receive(remaining_time);
remaining_time = m_server->Receive(remaining_time);
// if negative, the step took too long
last_remaining_time = std::max(0.0f, remaining_time);

} catch (con::PeerNotFoundException &e) {
infostream<<"Server: PeerNotFoundException"<<std::endl;
Expand Down Expand Up @@ -1084,15 +1094,15 @@ void Server::AsyncRunStep(float dtime, bool initial_step)
m_shutdown_state.tick(dtime, this);
}

void Server::Receive(float timeout)
float Server::Receive(float timeout)
{
ZoneScoped;
auto framemarker = FrameMarker("Server::Receive()-frame").started();

const u64 t0 = porting::getTimeUs();
const float timeout_us = timeout * 1e6f;
auto remaining_time_us = [&]() -> float {
return std::max(0.0f, timeout_us - (porting::getTimeUs() - t0));
return timeout_us - (porting::getTimeUs() - t0);
};

NetworkPacket pkt;
Expand All @@ -1102,12 +1112,15 @@ void Server::Receive(float timeout)
peer_id = 0;
try {
if (!m_con->ReceiveTimeoutMs(&pkt,
(u32)remaining_time_us() / 1000)) {
(u32)std::max(0.0f, remaining_time_us()) / 1000)) {
// No incoming data.
// Already break if there's 1ms left, as ReceiveTimeoutMs is too coarse
// and a faster server-step is better than busy waiting.
if (remaining_time_us() < 1000.0f)
break;
// The caller can accumulate the return value, and give us a larger
// timeout next time.
float remaining = remaining_time_us();
if (remaining < 1000.0f)
return remaining * 1e-6f;
else
continue;
}
Expand Down
6 changes: 5 additions & 1 deletion src/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,11 @@ class Server : public con::PeerHandler, public MapEventReceiver,

// This is run by ServerThread and does the actual processing
void AsyncRunStep(float dtime, bool initial_step = false);
void Receive(float timeout);
// timeout: How long this function should take, in seconds. It waits this long
// even if there are some incoming packets. (Negative values allowed.)
// Returns the remaining time from timeout (timeout minus time it actually
// took), can be negative (took too long) or positive (<1 ms remaining).
float Receive(float timeout);
void yieldToOtherThreads(float dtime);

PlayerSAO* StageTwoClientInit(session_t peer_id);
Expand Down

0 comments on commit a199672

Please sign in to comment.