From 27b5ce7ef44d91a3bfb16da564b404384169b1f5 Mon Sep 17 00:00:00 2001 From: jyelon Date: Tue, 2 Dec 2025 18:06:23 -0500 Subject: [PATCH] Add mini-diffs and change the difference transmission frequency. --- luprex/cpp/core/lpxclient.cpp | 2 +- luprex/cpp/core/lpxserver.cpp | 35 ++++++++++++++++++++++-------- luprex/cpp/core/world-diffxmit.cpp | 28 ++++++++++++++---------- luprex/cpp/core/world.hpp | 17 +++++++++------ 4 files changed, 54 insertions(+), 28 deletions(-) diff --git a/luprex/cpp/core/lpxclient.cpp b/luprex/cpp/core/lpxclient.cpp index 55820d4f..bd8c4ae5 100644 --- a/luprex/cpp/core/lpxclient.cpp +++ b/luprex/cpp/core/lpxclient.cpp @@ -201,7 +201,7 @@ public: world_to_synchronous(); try { DebugCollector dbc(""); - int64_t nactor = world_->patch_everything(sb, &dbc); + int64_t nactor = world_->patch(sb, &dbc); if (nactor != actor_id_) change_actor_id(nactor); dbc.dump(stdostream()); } catch (const StreamException &sexcept) { diff --git a/luprex/cpp/core/lpxserver.cpp b/luprex/cpp/core/lpxserver.cpp index 66a34cf5..26d5110c 100644 --- a/luprex/cpp/core/lpxserver.cpp +++ b/luprex/cpp/core/lpxserver.cpp @@ -14,7 +14,8 @@ public: int64_t actor_id_; SharedChannel channel_; UniqueWorld sync_; - double last_diff_; + double last_full_diff_; + double last_mini_diff_; bool async_diff_; }; using UniqueClient = std::unique_ptr; @@ -117,13 +118,13 @@ public: client.reset(); } - void send_diffs(UniqueClient &client) { + void send_diffs(UniqueClient &client, bool full) { StreamBuffer *sb = client->channel_->out(); sb->write_uint8(util::MSG_DIFF); sb->write_uint32(0); int64_t tw_1 = sb->total_writes(); //stdostream() << "Sending diffs to client " << client->actor_id_ << std::endl; - client->sync_->diff_everything(client->actor_id_, master_.get(), sb); + client->sync_->diff(client->actor_id_, full, master_.get(), sb); int64_t tw_2 = sb->total_writes(); sb->overwrite_int32(tw_1, tw_2 - tw_1); } @@ -218,7 +219,8 @@ public: // TODO: initialize the login actor on the master. client->channel_ = std::move(chan); client->async_diff_ = true; - client->last_diff_ = -100.0; + client->last_full_diff_ = -100.0; + client->last_mini_diff_ = -100.0; client->sync_.reset(new World(WORLD_TYPE_PREDICTIVE)); // This login actor is never used, it is just to preserve the invariant that // the client model and the server synchronous model are identical. @@ -254,11 +256,26 @@ public: if (client == nullptr) continue; // Possibly send a diff. - double diffdelay = 5.0; - if (client->async_diff_) diffdelay = 0.1; - if (clock >= client->last_diff_ + diffdelay) { - send_diffs(client); - client->last_diff_ = clock; + // Currently, it's configured to send about + // ten mini-diffs per second, and two full diffs + // per second. It actually only considers sending + // a full diff if it already has decided to send + // a mini diff. + double mini_delay = 0.1; + double full_delay = 0.45; + if (client->async_diff_) { + mini_delay = 0.05; + full_delay = 0.1; + } + if (clock >= client->last_mini_diff_ + mini_delay) { + if (clock >= client->last_full_diff_ + full_delay) { + send_diffs(client, true); + client->last_full_diff_ = clock; + client->last_mini_diff_ = clock; + } else { + send_diffs(client, false); + client->last_mini_diff_ = clock; + } client->async_diff_ = false; } } diff --git a/luprex/cpp/core/world-diffxmit.cpp b/luprex/cpp/core/world-diffxmit.cpp index 3d8c16ec..b8ef1ae6 100644 --- a/luprex/cpp/core/world-diffxmit.cpp +++ b/luprex/cpp/core/world-diffxmit.cpp @@ -357,23 +357,29 @@ void World::diff_globals(World *master, StreamBuffer *sb) { assert(tsb.empty()); } -int64_t World::patch_everything(StreamBuffer *sb, DebugCollector *dbc) { - DebugBlock dbb(dbc, "patch_everything"); +int64_t World::patch(StreamBuffer *sb, DebugCollector *dbc) { + DebugBlock dbb(dbc, "patch"); int64_t actor_id = patch_actor(sb, dbc); patch_visible(sb, dbc); - patch_luatabs(sb, dbc); - patch_tanclass(sb, dbc); - patch_source(sb, dbc); - patch_globals(sb, dbc); + bool full = sb->read_bool(); + if (full) { + patch_luatabs(sb, dbc); + patch_tanclass(sb, dbc); + patch_source(sb, dbc); + patch_globals(sb, dbc); + } return actor_id; } -void World::diff_everything(int64_t actor_id, World *master, StreamBuffer *sb) { +void World::diff(int64_t actor_id, bool full, World *master, StreamBuffer *sb) { diff_actor(actor_id, master, sb); util::IdVector visible = get_visible_union(actor_id, master); diff_visible(visible, master, sb); - diff_luatabs(actor_id, master, sb); - diff_tanclass(actor_id, master, sb); - diff_source(master, sb); - diff_globals(master, sb); + sb->write_bool(full); + if (full) { + diff_luatabs(actor_id, master, sb); + diff_tanclass(actor_id, master, sb); + diff_source(master, sb); + diff_globals(master, sb); + } } diff --git a/luprex/cpp/core/world.hpp b/luprex/cpp/core/world.hpp index 12826f6b..edd96a2a 100644 --- a/luprex/cpp/core/world.hpp +++ b/luprex/cpp/core/world.hpp @@ -497,7 +497,7 @@ public: public: /////////////////////////////////////////////////////////// // - // world-difftab: Nonrecursive table comparison + // difference transmission internals related to table comparison // // These routines compare tables in the master lua to the corresponding // tables in the synchronous lua. This is a nonrecursive process, because @@ -514,10 +514,9 @@ public: void patch_tangible_classes(StreamBuffer *sb, DebugCollector *dbc); void diff_tangible_classes(const IdVector &basis, lua_State *master, StreamBuffer *sb); -public: /////////////////////////////////////////////////////////// // - // Difference transmission + // Difference transmission internals // /////////////////////////////////////////////////////////// @@ -540,11 +539,15 @@ public: void patch_globals(StreamBuffer *sb, DebugCollector *dbc); void diff_globals(World *master, StreamBuffer *sb); - - // This is the main entry point for difference transmission. + + /////////////////////////////////////////////////////////// // - int64_t patch_everything(StreamBuffer *sb, DebugCollector *dbc); - void diff_everything(int64_t actor, World *master, StreamBuffer *sb); + // Difference transmission entry point. + // + /////////////////////////////////////////////////////////// + + int64_t patch(StreamBuffer *sb, DebugCollector *dbc); + void diff(int64_t actor, bool full, World *master, StreamBuffer *sb); public: ///////////////////////////////////////////////////////////