Performance optimizations to resolve long stalls - #5393
Conversation
akleshchev
commented
Feb 10, 2026
- Inventory was parsing a large message for over a second, moved that to a thread worker.
- Fast cache was locked from accessing id map by texture thread on a general cache mutex. Added map specific mutex.
There was a problem hiding this comment.
Pull request overview
This PR targets viewer stalls by offloading expensive HTTP response parsing from the main thread and reducing lock contention in the texture cache by introducing a more granular mutex for header ID map access.
Changes:
- Added a dedicated mutex for
LLTextureCache::mHeaderIDMapand updated call sites to lock the ID map independently of the broader header mutex. - Updated
LLCoreHttpUtil::HttpCoroHandlerto post large-body success-response parsing to the"General"WorkQueue, replying back on"mainloop". - Refactored portions of
HttpCoroHandler(const-correctness and shared reply posting) to support the threaded parsing flow.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
indra/newview/lltexturecache.h |
Introduces mHeaderIDMapMutex to support finer-grained locking for the header ID map. |
indra/newview/lltexturecache.cpp |
Switches mHeaderIDMap accesses to use the new mutex to reduce contention and stalls. |
indra/llmessage/llcorehttputil.h |
Extends HttpCoroHandler to support shared_from_this() and updates virtual method constness to align with new flow. |
indra/llmessage/llcorehttputil.cpp |
Adds WorkQueue-based off-main-thread parsing for large HTTP success bodies and centralizes reply posting. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| posted = main_queue->postTo( | ||
| general_queue, | ||
| [handler = shared_from_this(), response, status]() // Work done on general queue | ||
| { | ||
| std::pair<LLSD, LLCore::HttpStatus> result; | ||
| result.second = status; | ||
| try | ||
| { | ||
| result.first = handler->handleSuccess(response, result.second); | ||
| } | ||
| catch (std::bad_alloc&) | ||
| { | ||
| LLError::LLUserWarningMsg::showOutOfMemory(); | ||
| LL_ERRS("CoreHTTP") << "Failed to allocate memory for response handling (threaded)." << LL_ENDL; | ||
| } | ||
| // LLSD is not thread safe! Be carefull with moving the result around. | ||
| return result; | ||
| }, | ||
| [handler = shared_from_this(), response](std::pair<LLSD, LLCore::HttpStatus> result) mutable // Callback to main thread | ||
| { | ||
| handler->replyPost(response, result.second, result.first); | ||
| response->release(); | ||
| }); |
There was a problem hiding this comment.
This posts a std::pair<LLSD, HttpStatus> through WorkQueue::postTo(), which internally copies the posted std::function into the queue; that implies copying/moving LLSD across threads. llsd.h explicitly warns that copying/sharing LLSD across threads is unsafe and requires special ownership-transfer patterns. To avoid LLSD cross-thread copies, return a thread-safe wrapper (e.g., std::shared_ptr<LLSD> / heap-allocated LLSD with ownership transfer) or serialize the parsed result into a thread-safe form for transport back to the main thread.
There was a problem hiding this comment.
std::shared_ptr wouldn't help as LLSD consists of multiple insecure elements, wrapping each is not practical, serializing LLSD won't help either as it is huge, deserializing will cause a stall.
As I understant it, before callback gets executed, usage of response's llsd should already be cleaned up and the std::pair should be moved, not copied. If that isn't the case and there will be problems I will figure something out. Perhaps LLSD can be stored in the handler and be mutex protected.
| try | ||
| constexpr size_t MAX_BODY_SIZE_THRESHOLD = 65536; | ||
| bool posted = false; | ||
| // Some messsages (ex: AISAPI) can return large bodies. |
There was a problem hiding this comment.
Spelling: "messsages" -> "messages".
| // Some messsages (ex: AISAPI) can return large bodies. | |
| // Some messages (ex: AISAPI) can return large bodies. |