diff options
| -rw-r--r-- | indra/llmessage/llcoproceduremanager.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/llaisapi.cpp | 48 | ||||
| -rw-r--r-- | indra/newview/llaisapi.h | 3 | ||||
| -rw-r--r-- | indra/newview/lllandmarklist.cpp | 40 | 
4 files changed, 78 insertions, 15 deletions
| diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp index 26684a4d9e..a4fe3a2a8e 100644 --- a/indra/llmessage/llcoproceduremanager.cpp +++ b/indra/llmessage/llcoproceduremanager.cpp @@ -360,7 +360,7 @@ LLUUID LLCoprocedurePool::enqueueCoprocedure(const std::string &name, LLCoproced      }      // The queue should never fill up. -    LL_ERRS("CoProcMgr") << "Enqueue failed (" << unsigned(pushed) << ")" << LL_ENDL; +    LL_ERRS("CoProcMgr") << "Enqueue into '" << name << "' failed (" << unsigned(pushed) << ")" << LL_ENDL;      return {};                      // never executed, pacify the compiler  } diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index ee49125711..005259bcb8 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -44,6 +44,10 @@  const std::string AISAPI::INVENTORY_CAP_NAME("InventoryAPIv3");  const std::string AISAPI::LIBRARY_CAP_NAME("LibraryAPIv3"); +std::list<AISAPI::ais_query_item_t> AISAPI::sPostponedQuery; + +const S32 MAX_SIMULTANEOUS_COROUTINES = 2048; +  //-------------------------------------------------------------------------  /*static*/  bool AISAPI::isAvailable() @@ -366,9 +370,51 @@ void AISAPI::UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t  /*static*/  void AISAPI::EnqueueAISCommand(const std::string &procName, LLCoprocedureManager::CoProcedure_t proc)  { +    LLCoprocedureManager &inst = LLCoprocedureManager::instance(); +    S32 pending_in_pool = inst.countPending("AIS");      std::string procFullName = "AIS(" + procName + ")"; -    LLCoprocedureManager::instance().enqueueCoprocedure("AIS", procFullName, proc); +    if (pending_in_pool < MAX_SIMULTANEOUS_COROUTINES) +    { +        inst.enqueueCoprocedure("AIS", procFullName, proc); +    } +    else +    { +        // As I understand it, coroutines have built-in 'pending' pool +        // but unfortunately it has limited size which inventory often goes over +        // so this is a workaround to not overfill it. +        if (sPostponedQuery.empty()) +        { +            sPostponedQuery.push_back(ais_query_item_t(procFullName, proc)); +            gIdleCallbacks.addFunction(onIdle, NULL); +        } +        else +        { +            sPostponedQuery.push_back(ais_query_item_t(procFullName, proc)); +        } +    } +} +/*static*/ +void AISAPI::onIdle(void *userdata) +{ +    if (!sPostponedQuery.empty()) +    { +        LLCoprocedureManager &inst = LLCoprocedureManager::instance(); +        S32 pending_in_pool = inst.countPending("AIS"); +        while (pending_in_pool < MAX_SIMULTANEOUS_COROUTINES && !sPostponedQuery.empty()) +        { +            ais_query_item_t &item = sPostponedQuery.front(); +            inst.enqueueCoprocedure("AIS", item.first, item.second); +            sPostponedQuery.pop_front(); +            pending_in_pool++; +        } +    } +     +    if (sPostponedQuery.empty()) +    { +        // Nothing to do anymore +        gIdleCallbacks.deleteFunction(onIdle, NULL); +    }  }  /*static*/ diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index fc1a6c0871..856f3fc180 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -71,6 +71,7 @@ private:          const std::string, LLSD, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t) > invokationFn_t;      static void EnqueueAISCommand(const std::string &procName, LLCoprocedureManager::CoProcedure_t proc); +    static void onIdle(void *userdata); // launches postponed AIS commands      static std::string getInvCap();      static std::string getLibCap(); @@ -79,6 +80,8 @@ private:          invokationFn_t invoke, std::string url, LLUUID targetId, LLSD body,           completion_t callback, COMMAND_TYPE type); +    typedef std::pair<std::string, LLCoprocedureManager::CoProcedure_t> ais_query_item_t; +    static std::list<ais_query_item_t> sPostponedQuery;  };  class AISUpdate diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp index 1fc70cd6d6..b4236c406b 100644 --- a/indra/newview/lllandmarklist.cpp +++ b/indra/newview/lllandmarklist.cpp @@ -40,8 +40,8 @@  LLLandmarkList gLandmarkList;  // number is mostly arbitrary, but it should be below DEFAULT_QUEUE_SIZE pool size, -// which is 4096, to not overfill the pool if user has more than 4K of landmarks, -// and low number helps with not flooding server with requests +// which is 4096, to not overfill the pool if user has more than 4K of landmarks +// and it should leave some space for other potential simultaneous asset request  const S32 MAX_SIMULTANEOUS_REQUESTS = 512; @@ -98,7 +98,11 @@ LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t          if (mRequestedList.size() > MAX_SIMULTANEOUS_REQUESTS)          { -            // Postpone download till queu is emptier +            // Workarounds for corutines pending list size limit: +            // Postpone download till queue is emptier. +            // Coroutines have own built in 'pending' list, but unfortunately +            // it is too small compared to potential amount of landmarks +            // or assets.              mWaitList.insert(asset_uuid);              return NULL;          } @@ -176,17 +180,27 @@ void LLLandmarkList::processGetAssetReply(          // todo: this should clean mLoadedCallbackMap!  	} -    if (!gLandmarkList.mWaitList.empty()) +    // getAssetData can fire callback immediately, causing +    // a recursion which is suboptimal for very large wait list. +    // 'scheduling' indicates that we are inside request and +    // shouldn't be launching more requests. +    static bool scheduling = false; +    if (!scheduling && !gLandmarkList.mWaitList.empty())      { -        // start new download from wait list -        landmark_uuid_list_t::iterator iter = gLandmarkList.mWaitList.begin(); -        LLUUID asset_uuid = *iter; -        gLandmarkList.mWaitList.erase(iter); -        gAssetStorage->getAssetData(asset_uuid, -            LLAssetType::AT_LANDMARK, -            LLLandmarkList::processGetAssetReply, -            NULL); -        gLandmarkList.mRequestedList[asset_uuid] = gFrameTimeSeconds; +        scheduling = true; +        while (!gLandmarkList.mWaitList.empty() && gLandmarkList.mRequestedList.size() < MAX_SIMULTANEOUS_REQUESTS) +        { +            // start new download from wait list +            landmark_uuid_list_t::iterator iter = gLandmarkList.mWaitList.begin(); +            LLUUID asset_uuid = *iter; +            gLandmarkList.mWaitList.erase(iter); +            gAssetStorage->getAssetData(asset_uuid, +                LLAssetType::AT_LANDMARK, +                LLLandmarkList::processGetAssetReply, +                NULL); +            gLandmarkList.mRequestedList[asset_uuid] = gFrameTimeSeconds; +        } +        scheduling = false;      }  } | 
