From dec49dad211ff77235c9554ed14e7a3fc2ee7683 Mon Sep 17 00:00:00 2001 From: Rye Mutt <rye@alchemyviewer.org> Date: Wed, 14 Jul 2021 20:58:50 -0400 Subject: [PATCH] Use SPSC queue in image pool workers for deep request pipelining --- indra/deps/CMakeLists.txt | 7 ++++++ indra/llimage/CMakeLists.txt | 1 + indra/llimage/llimageworker.cpp | 41 +++++++++++++++------------------ 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/indra/deps/CMakeLists.txt b/indra/deps/CMakeLists.txt index 939a299e1d4..9f794c072f5 100644 --- a/indra/deps/CMakeLists.txt +++ b/indra/deps/CMakeLists.txt @@ -54,6 +54,11 @@ FetchContent_Declare( GIT_REPOSITORY https://git.alchemyviewer.org/alchemy/mirrors/abseil-cpp.git GIT_TAG 9a7e447c511dae7276ab65fde4d04f6ed52b39c9 ) +FetchContent_Declare( + readerwriterqueue + GIT_REPOSITORY https://github.com/cameron314/readerwriterqueue + GIT_TAG v1.0.5 +) # This is a hack because absl has dumb cmake set(OLD_BUILD_TEST ${BUILD_TESTING}) @@ -94,5 +99,7 @@ set(JSON_Install OFF CACHE INTERNAL "") set(JSON_BuildTests OFF CACHE INTERNAL "") FetchContent_MakeAvailable(nlohmann_json) +FetchContent_MakeAvailable(readerwriterqueue) + unset(CMAKE_FOLDER) unset(CMAKE_POSITION_INDEPENDENT_CODE) diff --git a/indra/llimage/CMakeLists.txt b/indra/llimage/CMakeLists.txt index 1dcd1fd8ecb..33a901c0a41 100644 --- a/indra/llimage/CMakeLists.txt +++ b/indra/llimage/CMakeLists.txt @@ -79,6 +79,7 @@ target_link_libraries(llimage ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} + readerwriterqueue ) if(${CMAKE_VERSION} VERSION_GREATER "3.15.0") diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp index f5a580865bd..8319b646e16 100644 --- a/indra/llimage/llimageworker.cpp +++ b/indra/llimage/llimageworker.cpp @@ -28,54 +28,49 @@ #include "llimageworker.h" #include "llimagedxt.h" +#include <readerwriterqueue.h> std::atomic< U32 > sImageThreads; class PoolWorkerThread : public LLThread { public: - PoolWorkerThread(std::string name) : LLThread(name), - mCurrentRequest(NULL) + PoolWorkerThread(std::string name) : LLThread(name), mRequestQueue(30) { } + virtual void run() { while (!isQuitting()) { - auto *pReq = mCurrentRequest.exchange(nullptr); - - if (pReq) - pReq->processRequestIntern(); - checkPause(); + checkPause(); + + LLImageDecodeThread::ImageRequest* req = nullptr; + while (!isQuitting() && mRequestQueue.try_dequeue(req)) + { + if (req) + { + req->processRequestIntern(); + } + } } } - bool isBusy() - { - auto *pReq = mCurrentRequest.load(); - if (!pReq) - return false; - - auto status = pReq->getStatus(); - - return status == LLQueuedThread::STATUS_QUEUED || status == LLQueuedThread::STATUS_INPROGRESS; - } bool runCondition() - { - return mCurrentRequest != NULL; + { + return mRequestQueue.size_approx() > 0; } bool setRequest(LLImageDecodeThread::ImageRequest* req) { - LLImageDecodeThread::ImageRequest* pOld{ nullptr }; - bool bSuccess = mCurrentRequest.compare_exchange_strong(pOld, req); + bool bSuccess = mRequestQueue.try_enqueue(req); wake(); return bSuccess; } private: - std::atomic< LLImageDecodeThread::ImageRequest * > mCurrentRequest; + moodycamel::ReaderWriterQueue<LLImageDecodeThread::ImageRequest*> mRequestQueue; }; //---------------------------------------------------------------------------- @@ -344,7 +339,7 @@ bool LLImageDecodeThread::enqueRequest(ImageRequest * req) mLastPoolAllocation = 0; } auto& thread = mThreadPool[mLastPoolAllocation++]; - if (!thread->isBusy() && thread->setRequest(req)) + if (thread->setRequest(req)) { return true; } -- GitLab