perf: process 16 chunks/player/tick on dedicated server, revert async save
Chunk loading now batches up to 16 nearest-first requests per player per tick on dedicated server (client stays at 1), improving tick recovery time after player join. Reverts the async save system -- the background thread snapshot/compress path added complexity without measurable benefit. Autosave on Windows64 server now uses the standard synchronous flush like client, in preparation for a proper async implementation from upstream.
This commit is contained in:
@@ -487,37 +487,52 @@ void PlayerChunkMap::getChunkAndRemovePlayer(int x, int z, shared_ptr<ServerPlay
|
||||
}
|
||||
|
||||
// 4J - added - actually create & add player to a playerchunk, if there is one queued for this player.
|
||||
// Processes up to CHUNKS_PER_PLAYER_PER_TICK requests per call to speed up initial chunk loading.
|
||||
|
||||
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
|
||||
static const int CHUNKS_PER_PLAYER_PER_TICK = 16;
|
||||
#else
|
||||
static const int CHUNKS_PER_PLAYER_PER_TICK = 1;
|
||||
#endif
|
||||
|
||||
void PlayerChunkMap::tickAddRequests(shared_ptr<ServerPlayer> player)
|
||||
{
|
||||
if( addRequests.size() )
|
||||
{
|
||||
// Find the nearest chunk request to the player
|
||||
int px = static_cast<int>(player->x);
|
||||
int pz = static_cast<int>(player->z);
|
||||
int minDistSq = -1;
|
||||
|
||||
auto itNearest = addRequests.end();
|
||||
for (auto it = addRequests.begin(); it != addRequests.end(); it++)
|
||||
{
|
||||
if( it->player == player )
|
||||
for (int processed = 0; processed < CHUNKS_PER_PLAYER_PER_TICK; processed++)
|
||||
{
|
||||
// Find the nearest chunk request to the player
|
||||
int minDistSq = -1;
|
||||
auto itNearest = addRequests.end();
|
||||
for (auto it = addRequests.begin(); it != addRequests.end(); it++)
|
||||
{
|
||||
int xm = ( it->x * 16 ) + 8;
|
||||
int zm = ( it->z * 16 ) + 8;
|
||||
int distSq = (xm - px) * (xm - px) +
|
||||
(zm - pz) * (zm - pz);
|
||||
if( ( minDistSq == -1 ) || ( distSq < minDistSq ) )
|
||||
if( it->player == player )
|
||||
{
|
||||
minDistSq = distSq;
|
||||
itNearest = it;
|
||||
int xm = ( it->x * 16 ) + 8;
|
||||
int zm = ( it->z * 16 ) + 8;
|
||||
int distSq = (xm - px) * (xm - px) +
|
||||
(zm - pz) * (zm - pz);
|
||||
if( ( minDistSq == -1 ) || ( distSq < minDistSq ) )
|
||||
{
|
||||
minDistSq = distSq;
|
||||
itNearest = it;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we found one at all, then do this one
|
||||
if( itNearest != addRequests.end() )
|
||||
{
|
||||
getChunk(itNearest->x, itNearest->z, true)->add(itNearest->player);
|
||||
addRequests.erase(itNearest);
|
||||
// If we found one, process it and continue; otherwise done
|
||||
if( itNearest != addRequests.end() )
|
||||
{
|
||||
getChunk(itNearest->x, itNearest->z, true)->add(itNearest->player);
|
||||
addRequests.erase(itNearest);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -977,11 +977,8 @@ void ServerLevel::save(bool force, ProgressListener *progressListener, bool bAut
|
||||
|
||||
if (progressListener != nullptr) progressListener->progressStage(IDS_PROGRESS_SAVING_CHUNKS);
|
||||
|
||||
#if defined(_XBOX_ONE) || defined(__ORBIS__) || (defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD))
|
||||
// Autosave is a minimal save. Chunks are saved continuously by the
|
||||
// per-tick trickle save process (ServerChunkCache::tick), so we only
|
||||
// need to flush entity data here. The full chunkSource->save() would
|
||||
// redundantly re-save all dirty chunks and block the main thread.
|
||||
#if defined(_XBOX_ONE) || defined(__ORBIS__)
|
||||
// Our autosave is a minimal save. All the chunks are saves by the constant save process
|
||||
if(bAutosave)
|
||||
{
|
||||
chunkSource->saveAllEntities();
|
||||
|
||||
Reference in New Issue
Block a user