diff --git a/kit/Kit.cpp b/kit/Kit.cpp index 59d65edf9cb2..9ee6fce338b8 100644 --- a/kit/Kit.cpp +++ b/kit/Kit.cpp @@ -2300,7 +2300,7 @@ void Document::drainCallbacks() _websocketHandler->flush(); } -void Document::drainQueue() +void Document::drainQueue(bool isIDLE) { if (UnitKit::get().filterDrainQueue()) { @@ -2369,11 +2369,34 @@ void Document::drainQueue() { std::vector tileRequests = _queue->popWholeTileQueue(); - // Put requests that include tiles in the visible area to the front to handle those first - std::partition(tileRequests.begin(), tileRequests.end(), [this](const TileCombined& req) { - return isTileRequestInsideVisibleArea(req); }); - for (auto& tileCombined : tileRequests) - renderTiles(tileCombined); + if(isIDLE) + { + // Put requests that include tiles in the visible area to the front to handle those first + std::partition(tileRequests.begin(), tileRequests.end(), [this](const TileCombined& req) { + return isTileRequestInsideVisibleArea(req); }); + for (auto& tileCombined : tileRequests) + renderTiles(tileCombined); + + LOG_TRC("Kit TileCombined Items: " << tileRequests.size()); + } + else + { + // Limited time left, push-back all invisible tile-requests + size_t invisibleCount = 0; + for(TileCombined& tileCombined : tileRequests) + { + if( isTileRequestInsideVisibleArea(tileCombined) ) + { + renderTiles(tileCombined); + } else { + ++invisibleCount; + _queue->pushTileQueue(tileCombined.getTiles()); + } + } + LOG_TRC("Kit TileCombined Items: " << tileRequests.size() + << ", invisible " << invisibleCount << " " + << 100.0f * (float)invisibleCount / (float)tileRequests.size() << "%"); + } } } catch (const std::exception& exc) @@ -2742,12 +2765,12 @@ std::shared_ptr KitSocketPoll::create() // static } // process pending message-queue events. -void KitSocketPoll::drainQueue() +void KitSocketPoll::drainQueue(bool isIDLE) { SigUtil::checkDumpGlobalState(dump_kit_state); if (_document) - _document->drainQueue(); + _document->drainQueue(isIDLE); } // called from inside poll, inside a wakeup @@ -2798,10 +2821,10 @@ int KitSocketPoll::kitPoll(int timeoutMicroS) int maxExtraEvents = 15; int eventsSignalled = 0; - auto startTime = std::chrono::steady_clock::now(); + std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now(); // handle processtoidle waiting optimization - bool checkForIdle = ProcessToIdleDeadline >= startTime; + const bool checkForIdle = ProcessToIdleDeadline >= startTime; if (timeoutMicroS < 0) { @@ -2822,15 +2845,24 @@ int KitSocketPoll::kitPoll(int timeoutMicroS) if (_document && _document->needsQuickPoll()) realTimeout = 0; - if (poll(std::chrono::microseconds(realTimeout)) <= 0) + const int rc = poll(std::chrono::microseconds(realTimeout)); + if(rc > 0) + { + // poll successful w/o timeout, i.e. !IDLE client activity + const auto now = std::chrono::steady_clock::now(); + timeoutMicroS = + std::chrono::duration_cast(_pollEnd - now).count(); + ++eventsSignalled; + drainQueue(/*isIDLE=*/false); + } + else if(rc == 0) + { + // poll timed out, i.e. IDLE client in-activity + timeoutMicroS = 0; + drainQueue(/*isIDLE=*/realTimeout>0); + } + else // poll error break; - - const auto now = std::chrono::steady_clock::now(); - drainQueue(); - - timeoutMicroS = - std::chrono::duration_cast(_pollEnd - now).count(); - ++eventsSignalled; } while (timeoutMicroS > 0 && !SigUtil::getTerminationFlag() && maxExtraEvents-- > 0); } @@ -2849,7 +2881,7 @@ int KitSocketPoll::kitPoll(int timeoutMicroS) LOG_TRC("Poll of would not close gap - continuing"); } - drainQueue(); + drainQueue(/*isIDLE=*/false); if (_document) _document->trimAfterInactivity(); diff --git a/kit/Kit.hpp b/kit/Kit.hpp index 0fd3784deb61..5a49ffb71574 100644 --- a/kit/Kit.hpp +++ b/kit/Kit.hpp @@ -144,7 +144,7 @@ class KitSocketPoll final : public SocketPoll public: ~KitSocketPoll(); - void drainQueue(); + void drainQueue(bool isIDLE); static void dumpGlobalState(std::ostream& oss); static std::shared_ptr create(); @@ -349,7 +349,7 @@ class Document final : public std::enable_shared_from_this // poll is idle, are we ? void checkIdle(); - void drainQueue(); + void drainQueue(bool isIDLE); void drainCallbacks(); void dumpState(std::ostream& oss); diff --git a/kit/KitQueue.cpp b/kit/KitQueue.cpp index 154a37bac6f4..7c9e0fc5e8ce 100644 --- a/kit/KitQueue.cpp +++ b/kit/KitQueue.cpp @@ -640,6 +640,12 @@ void KitQueue::pushTileQueue(const Payload &value) _tileQueue.push_back(desc); } +void KitQueue::pushTileQueue(const std::vector& tiles) +{ + for(const TileDesc desc : tiles) + _tileQueue.push_back(desc); +} + std::string KitQueue::combineRemoveText(const StringVector& tokens) { std::string id; diff --git a/kit/KitQueue.hpp b/kit/KitQueue.hpp index 1177aae3ab8e..2f828b79803e 100644 --- a/kit/KitQueue.hpp +++ b/kit/KitQueue.hpp @@ -70,6 +70,7 @@ class KitQueue /// Tiles are special manage a separate queue of them void clearTileQueue() { _tileQueue.clear(); } void pushTileQueue(const Payload &value); + void pushTileQueue(const std::vector& tiles); void pushTileCombineRequest(const Payload &value); TileCombined popTileQueue(); std::vector popWholeTileQueue();