From b2f2070f95d39685715a9aa09032b82ce5056c6c Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Wed, 30 Jul 2025 11:36:55 +0300 Subject: [PATCH] Improve performance when hosting canvas with many objects --- src/DrawComponents/DrawComponent.cpp | 18 ++++++------------ src/DrawComponents/DrawComponent.hpp | 9 ++------- src/DrawingProgram/DrawingProgram.cpp | 3 +-- src/Server/MainServer.cpp | 27 ++++++++++++++++++--------- src/Server/ServerData.hpp | 1 + 5 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/DrawComponents/DrawComponent.cpp b/src/DrawComponents/DrawComponent.cpp index 5d8c5f1..10bcbef 100644 --- a/src/DrawComponents/DrawComponent.cpp +++ b/src/DrawComponents/DrawComponent.cpp @@ -74,27 +74,22 @@ void DrawComponent::server_send_erase_set(MainServer& server, const std::unorder void DrawComponent::server_send_update_temp(MainServer& server, ServerClientID id) { server.netServer->send_items_to_all_clients(UNRELIABLE_COMMAND_CHANNEL, CLIENT_UPDATE_COMPONENT, true, id, *this); - tempServerUpdateTimer = std::chrono::steady_clock::now(); - serverIsTempUpdate = true; } void DrawComponent::server_send_update_final(MainServer& server, ServerClientID id) { server.netServer->send_items_to_all_clients(RELIABLE_COMMAND_CHANNEL, CLIENT_UPDATE_COMPONENT, false, id, *this); - serverIsTempUpdate = false; } void DrawComponent::server_send_transform_many(MainServer& server, const std::vector>& transforms) { server.netServer->send_items_to_all_clients(RELIABLE_COMMAND_CHANNEL, CLIENT_TRANSFORM_MANY_COMPONENTS, transforms); } -void DrawComponent::server_update(MainServer& server, ServerClientID id) { - if(serverIsTempUpdate) { - float timeSince = std::chrono::duration_cast>(std::chrono::steady_clock::now() - tempServerUpdateTimer).count(); - if(timeSince >= 1.0f) { - server_send_update_final(server, id); - serverIsTempUpdate = false; - } +bool DrawComponent::server_update(MainServer& server, ServerClientID id, const std::chrono::time_point& tempServerUpdateTimer) { + if((std::chrono::steady_clock::now() - tempServerUpdateTimer) >= CLIENT_DRAWCOMP_DELAY_TIMER_DURATION) { + server_send_update_final(server, id); + return true; } + return false; } void DrawComponent::get_used_resources(std::unordered_set& v) const { @@ -112,8 +107,7 @@ bool DrawComponent::bounds_draw_check(const DrawData& drawData) const { void DrawComponent::check_timers(DrawingProgram& drawP) { if(delayedUpdatePtr) { - float updateDur = std::chrono::duration_cast>(std::chrono::steady_clock::now() - lastUpdateTime).count(); - if(updateDur > CLIENT_DRAWCOMP_DELAY_TIMER_DURATION) { + if(std::chrono::steady_clock::now() - lastUpdateTime > CLIENT_DRAWCOMP_DELAY_TIMER_DURATION) { update_from_delayed_ptr(); delayedUpdatePtr = nullptr; final_update(drawP); diff --git a/src/DrawComponents/DrawComponent.hpp b/src/DrawComponents/DrawComponent.hpp index 969835e..9fa0a01 100644 --- a/src/DrawComponents/DrawComponent.hpp +++ b/src/DrawComponents/DrawComponent.hpp @@ -14,7 +14,7 @@ #include #endif -#define CLIENT_DRAWCOMP_DELAY_TIMER_DURATION 5.0f +#define CLIENT_DRAWCOMP_DELAY_TIMER_DURATION std::chrono::seconds(6) #define DRAWCOMP_MAX_SHIFT_BEFORE_DISAPPEAR 20 #define DRAWCOMP_MIN_SHIFT_BEFORE_DISAPPEAR 11 @@ -71,18 +71,13 @@ class DrawComponent { void server_send_update_final(MainServer& server, ServerClientID id); static void server_send_transform_many(MainServer& server, const std::vector>& transforms); - std::chrono::time_point tempServerUpdateTimer; - bool serverIsTempUpdate = false; - std::weak_ptr collabListInfo; std::weak_ptr parentBvhNode; - void server_update(MainServer& server, ServerClientID id); + bool server_update(MainServer& server, ServerClientID id, const std::chrono::time_point& tempServerUpdateTimer); #ifndef IS_SERVER - std::chrono::time_point lastTransformTime; std::chrono::time_point lastUpdateTime; - std::shared_ptr delayedUpdatePtr = nullptr; bool bounds_draw_check(const DrawData& drawData) const; diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index 0358340..31eeab5 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -76,8 +76,7 @@ void DrawingProgram::init_client_callbacks() { if(!objPtr) return; std::shared_ptr& comp = objPtr->obj; - float dur = std::chrono::duration_cast>(std::chrono::steady_clock::now() - comp->lastUpdateTime).count(); - if(dur > CLIENT_DRAWCOMP_DELAY_TIMER_DURATION){ + if((std::chrono::steady_clock::now() - comp->lastUpdateTime) > CLIENT_DRAWCOMP_DELAY_TIMER_DURATION){ comp->delayedUpdatePtr = nullptr; message(*comp); if(isTemp) diff --git a/src/Server/MainServer.cpp b/src/Server/MainServer.cpp index 3c01f60..08a1619 100644 --- a/src/Server/MainServer.cpp +++ b/src/Server/MainServer.cpp @@ -197,16 +197,20 @@ MainServer::MainServer(World& initWorld, const std::string& serverLocalID): }); netServer->add_recv_callback(SERVER_UPDATE_COMPONENT, [&](std::shared_ptr client, cereal::PortableBinaryInputArchive& message) { bool isTemp; - ServerClientID idToTransform; - message(isTemp, idToTransform); - auto it = data.idToComponentMap.find(idToTransform); + ServerClientID idToUpdate; + message(isTemp, idToUpdate); + auto it = data.idToComponentMap.find(idToUpdate); if(it != data.idToComponentMap.end()) { std::shared_ptr& comp = it->second; message(*comp); - if(isTemp) - comp->server_send_update_temp(*this, idToTransform); - else - comp->server_send_update_final(*this, idToTransform); + if(isTemp) { + comp->server_send_update_temp(*this, idToUpdate); + data.updateComponentTimers[idToUpdate] = std::chrono::steady_clock::now(); + } + else { + comp->server_send_update_final(*this, idToUpdate); + data.updateComponentTimers.erase(idToUpdate); + } } }); netServer->add_recv_callback(SERVER_RESOURCE_INIT, [&](std::shared_ptr client, cereal::PortableBinaryInputArchive& message) { @@ -305,8 +309,13 @@ void MainServer::ensure_display_name_unique(std::string& displayName) { void MainServer::update() { netServer->update(); - for(auto& c : data.components) - c.second->server_update(*this, c.first); + std::erase_if(data.updateComponentTimers, [&](auto& c) { + auto& [id, timer] = c; + auto it = data.idToComponentMap.find(id); + if(it == data.idToComponentMap.end()) + return true; + return it->second->server_update(*this, id, timer); + }); if(std::chrono::steady_clock::now() - lastKeepAliveSent > std::chrono::seconds(2)) { netServer->send_items_to_all_clients(UNRELIABLE_COMMAND_CHANNEL, CLIENT_KEEP_ALIVE); lastKeepAliveSent = std::chrono::steady_clock::now(); diff --git a/src/Server/ServerData.hpp b/src/Server/ServerData.hpp index dae96b7..b4543fc 100644 --- a/src/Server/ServerData.hpp +++ b/src/Server/ServerData.hpp @@ -11,6 +11,7 @@ class ServerData { std::vector>> components; std::unordered_map> idToComponentMap; std::unordered_map resources; + std::unordered_map> updateComponentTimers; std::unordered_map bookmarks; void save(cereal::PortableBinaryOutputArchive& a) const; void write_to_file(cereal::PortableBinaryOutputArchive& a) const;