SL-14399: Ditch overflow queue LLViewerAssetStorage::mCoroWaitList.

mCoroWaitList was introduced to prevent an assertion failure crash:
LLCoprocedureManager never expects to fill LLCoprocedurePool::mPendingCoprocs
queue. The queue limit was arbitrarily set to 4096 some years ago, but in
practice LLViewerAssetStorage can post way more requests than that.

LLViewerAssetStorage checked whether the target LLCoprocedureManager pool's
queue looked close to full, and if so posted the pending request to its
mCoroWaitList instead. But then it had to override the base LLAssetStorage
method checkForTimeouts() to continually check whether pending tasks could be
moved from mCoroWaitList to LLCoprocedureManager.

A simpler solution is to enlarge LLCorpocedureManager::DEFAULT_QUEUE_SIZE, the
upper limit on mPendingCoprocs. Since mCoroWaitList was an unlimited queue,
making DEFAULT_QUEUE_SIZE "very large" does not increase the risk of runaway
memory consumption.
master
Nat Goodspeed 2022-12-07 09:50:02 -05:00
parent 59b826e66e
commit 769bf46a3f
3 changed files with 15 additions and 49 deletions

View File

@ -47,7 +47,10 @@ static const std::map<std::string, U32> DefaultPoolSizes{
};
static const U32 DEFAULT_POOL_SIZE = 5;
const U32 LLCoprocedureManager::DEFAULT_QUEUE_SIZE = 4096;
// SL-14399: When we teleport to a brand-new simulator, the coprocedure queue
// gets absolutely slammed with fetch requests. Make this queue effectively
// unlimited.
const U32 LLCoprocedureManager::DEFAULT_QUEUE_SIZE = 1024*1024;
//=========================================================================
class LLCoprocedurePool: private boost::noncopyable

View File

@ -134,14 +134,6 @@ LLViewerAssetStorage::~LLViewerAssetStorage()
// This class has dedicated coroutine pool, clean it up, otherwise coroutines will crash later.
LLCoprocedureManager::instance().close(VIEWER_ASSET_STORAGE_CORO_POOL);
}
while (mCoroWaitList.size() > 0)
{
CoroWaitList &request = mCoroWaitList.front();
// Clean up pending downloads, delete request and trigger callbacks
removeAndCallbackPendingDownloads(request.mId, request.mType, request.mId, request.mType, LL_ERR_NOERR, LLExtStat::NONE);
mCoroWaitList.pop_front();
}
}
// virtual
@ -346,28 +338,6 @@ void LLViewerAssetStorage::storeAssetData(
}
}
void LLViewerAssetStorage::checkForTimeouts()
{
LLAssetStorage::checkForTimeouts();
// Restore requests
LLCoprocedureManager* manager = LLCoprocedureManager::getInstance();
while (mCoroWaitList.size() > 0
&& manager->count(VIEWER_ASSET_STORAGE_CORO_POOL) < (LLCoprocedureManager::DEFAULT_QUEUE_SIZE - 1))
{
CoroWaitList &request = mCoroWaitList.front();
bool with_http = true;
bool is_temp = false;
LLViewerAssetStatsFF::record_enqueue(request.mType, with_http, is_temp);
manager->enqueueCoprocedure(VIEWER_ASSET_STORAGE_CORO_POOL, "LLViewerAssetStorage::assetRequestCoro",
boost::bind(&LLViewerAssetStorage::assetRequestCoro, this, request.mRequest, request.mId, request.mType, request.mCallback, request.mUserData));
mCoroWaitList.pop_front();
}
}
/**
* @brief Allocate and queue an asset fetch request for the viewer
*
@ -424,21 +394,18 @@ void LLViewerAssetStorage::queueRequestHttp(
// This is the same as the current UDP logic - don't re-request a duplicate.
if (!duplicate)
{
// Coroutine buffer has fixed size (synchronization buffer, so we have no alternatives), so buffer any request above limit
LLCoprocedureManager* manager = LLCoprocedureManager::getInstance();
if (manager->count(VIEWER_ASSET_STORAGE_CORO_POOL) < (LLCoprocedureManager::DEFAULT_QUEUE_SIZE - 1))
{
bool with_http = true;
bool is_temp = false;
LLViewerAssetStatsFF::record_enqueue(atype, with_http, is_temp);
manager->enqueueCoprocedure(VIEWER_ASSET_STORAGE_CORO_POOL, "LLViewerAssetStorage::assetRequestCoro",
boost::bind(&LLViewerAssetStorage::assetRequestCoro, this, req, uuid, atype, callback, user_data));
}
else
{
mCoroWaitList.emplace_back(req, uuid, atype, callback, user_data);
}
bool with_http = true;
bool is_temp = false;
LLViewerAssetStatsFF::record_enqueue(atype, with_http, is_temp);
manager->enqueueCoprocedure(
VIEWER_ASSET_STORAGE_CORO_POOL,
"LLViewerAssetStorage::assetRequestCoro",
[this, req, uuid, atype, callback, user_data]
(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t&, const LLUUID&)
{
assetRequestCoro(req, uuid, atype, callback, user_data);
});
}
}

View File

@ -65,8 +65,6 @@ public:
bool user_waiting=FALSE,
F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT) override;
void checkForTimeouts() override;
protected:
void _queueDataRequest(const LLUUID& uuid,
LLAssetType::EType type,
@ -118,8 +116,6 @@ protected:
LLGetAssetCallback mCallback;
void *mUserData;
};
typedef std::list<CoroWaitList> wait_list_t;
wait_list_t mCoroWaitList;
std::string mViewerAssetUrl;
S32 mCountRequests;