WIP: Added AIPerService::Approvement
This commit is contained in:
@@ -71,7 +71,7 @@ void intrusive_ptr_release(RefCountedThreadSafePerService* per_service)
|
||||
using namespace AICurlPrivate;
|
||||
|
||||
AIPerService::AIPerService(void) :
|
||||
mQueuedCommands(0), mAdded(0), mQueueEmpty(false),
|
||||
mApprovedRequests(0), mQueuedCommands(0), mAdded(0), mQueueEmpty(false),
|
||||
mQueueFull(false), mRequestStarvation(false), mHTTPBandwidth(25), // 25 = 1000 ms / 40 ms.
|
||||
mConcurrectConnections(CurlConcurrentConnectionsPerService),
|
||||
mMaxPipelinedRequests(CurlConcurrentConnectionsPerService)
|
||||
@@ -355,3 +355,14 @@ void AIPerService::adjust_concurrent_connections(int increment)
|
||||
}
|
||||
}
|
||||
|
||||
void AIPerService::Approvement::honored(void)
|
||||
{
|
||||
if (!mHonored)
|
||||
{
|
||||
mHonored = true;
|
||||
AICurlPrivate::PerService_wat per_service_w(*mPerServicePtr);
|
||||
llassert(per_service_w->mApprovedRequests > 0);
|
||||
per_service_w->mApprovedRequests--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,6 +114,7 @@ class AIPerService {
|
||||
private:
|
||||
typedef std::deque<AICurlPrivate::BufferedCurlEasyRequestPtr> queued_request_type;
|
||||
|
||||
int mApprovedRequests; // The number of approved requests by wantsMoreHTTPRequestsFor that were not added to the command queue yet.
|
||||
int mQueuedCommands; // Number of add commands (minus remove commands) with this host in the command queue.
|
||||
int mAdded; // Number of active easy handles with this host.
|
||||
queued_request_type mQueuedRequests; // Waiting (throttled) requests.
|
||||
@@ -188,7 +189,7 @@ class AIPerService {
|
||||
// Add queued easy handle (if any) to the multi handle. The request is removed from the queue,
|
||||
// followed by either a call to added_to_multi_handle() or to queue() to add it back.
|
||||
|
||||
S32 pipelined_requests(void) const { return mQueuedCommands + mQueuedRequests.size() + mAdded; }
|
||||
S32 pipelined_requests(void) const { return mApprovedRequests + mQueuedCommands + mQueuedRequests.size() + mAdded; }
|
||||
|
||||
AIAverage& bandwidth(void) { return mHTTPBandwidth; }
|
||||
AIAverage const& bandwidth(void) const { return mHTTPBandwidth; }
|
||||
@@ -212,6 +213,17 @@ class AIPerService {
|
||||
// Return true if too much bandwidth is being used.
|
||||
static bool checkBandwidthUsage(AIPerServicePtr const& per_service, U64 sTime_40ms);
|
||||
|
||||
// A helper class to decrement mApprovedRequests after requests approved by wantsMoreHTTPRequestsFor were handled.
|
||||
class Approvement {
|
||||
private:
|
||||
AIPerServicePtr mPerServicePtr;
|
||||
bool mHonored;
|
||||
public:
|
||||
Approvement(AIPerServicePtr const& per_service) : mPerServicePtr(per_service), mHonored(false) { }
|
||||
~Approvement() { honored(); }
|
||||
void honored(void);
|
||||
};
|
||||
|
||||
private:
|
||||
// Disallow copying.
|
||||
AIPerService(AIPerService const&);
|
||||
|
||||
@@ -2650,6 +2650,7 @@ bool AIPerService::wantsMoreHTTPRequestsFor(AIPerServicePtr const& per_service)
|
||||
{
|
||||
PerService_wat per_service_w(*per_service);
|
||||
S32 const pipelined_requests_per_service = per_service_w->pipelined_requests();
|
||||
llassert(pipelined_requests_per_service >= 0 && pipelined_requests_per_service <= 16);
|
||||
reject = pipelined_requests_per_service >= per_service_w->mMaxPipelinedRequests;
|
||||
equal = pipelined_requests_per_service == per_service_w->mMaxPipelinedRequests;
|
||||
increment_threshold = per_service_w->mRequestStarvation;
|
||||
@@ -2672,6 +2673,13 @@ bool AIPerService::wantsMoreHTTPRequestsFor(AIPerServicePtr const& per_service)
|
||||
reject = !equal;
|
||||
}
|
||||
}
|
||||
if (!reject)
|
||||
{
|
||||
// Before releasing the lock on per_service, stop other threads from getting a
|
||||
// too small value from pipelined_requests() and approving too many requests.
|
||||
per_service_w->mApprovedRequests++;
|
||||
llassert(per_service_w->mApprovedRequests <= 16);
|
||||
}
|
||||
}
|
||||
if (reject)
|
||||
{
|
||||
@@ -2683,6 +2691,7 @@ bool AIPerService::wantsMoreHTTPRequestsFor(AIPerServicePtr const& per_service)
|
||||
if (checkBandwidthUsage(per_service, sTime_40ms))
|
||||
{
|
||||
// Too much bandwidth is being used, either in total or for this service.
|
||||
PerService_wat(*per_service)->mApprovedRequests--; // Not approved after all.
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2714,6 +2723,10 @@ bool AIPerService::wantsMoreHTTPRequestsFor(AIPerServicePtr const& per_service)
|
||||
reject = !equal;
|
||||
}
|
||||
}
|
||||
if (reject)
|
||||
{
|
||||
PerService_wat(*per_service)->mApprovedRequests--; // Not approved after all.
|
||||
}
|
||||
return !reject;
|
||||
}
|
||||
|
||||
@@ -2773,6 +2786,8 @@ bool AIPerService::checkBandwidthUsage(AIPerServicePtr const& per_service, U64 s
|
||||
}
|
||||
|
||||
// Throttle this service if it uses too much bandwidth.
|
||||
// Warning: this requires max_bandwidth * 1024 to fit in a size_t.
|
||||
// On 32 bit that means that HTTPThrottleBandwidth must be less than 33554 kbps.
|
||||
return (service_bandwidth > (max_bandwidth * throttle_fraction_w->fraction / 1024));
|
||||
}
|
||||
|
||||
|
||||
@@ -175,7 +175,10 @@
|
||||
<key>HTTPThrottleBandwidth</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>The bandwidth (in kbit/s) to strive for</string>
|
||||
<string>The bandwidth (in kbit/s) to strive for. Smaller values might reduce network
|
||||
congestion (sim ping time, aka avatar responsiveness). Higher values might download
|
||||
textures and the inventory faster, although in some cases a too high value might
|
||||
actually slow that down due to serverside throttling. If unsure, choose 2000.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
@@ -4468,7 +4471,7 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>16</integer>
|
||||
<integer>8</integer>
|
||||
</map>
|
||||
<key>CurlTimeoutDNSLookup</key>
|
||||
<map>
|
||||
|
||||
@@ -604,6 +604,10 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
|
||||
{
|
||||
return; // Wait.
|
||||
}
|
||||
// If AIPerService::wantsMoreHTTPRequestsFor returns true, then it approved ONE request.
|
||||
// The code below might fire off zero, one or even more than one requests however!
|
||||
// This object keeps track of that.
|
||||
AIPerService::Approvement approvement(mPerServicePtr);
|
||||
|
||||
U32 item_count=0;
|
||||
U32 folder_count=0;
|
||||
@@ -698,6 +702,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
|
||||
{
|
||||
LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body, recursive_cats);
|
||||
LLHTTPClient::post_nb(url, folder_request_body, fetcher);
|
||||
approvement.honored();
|
||||
}
|
||||
if (folder_request_body_lib["folders"].size())
|
||||
{
|
||||
@@ -705,6 +710,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
|
||||
|
||||
LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body_lib, recursive_cats);
|
||||
LLHTTPClient::post_nb(url_lib, folder_request_body_lib, fetcher);
|
||||
approvement.honored();
|
||||
}
|
||||
}
|
||||
if (item_count)
|
||||
@@ -723,6 +729,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
|
||||
body["items"] = item_request_body;
|
||||
|
||||
LLHTTPClient::post_nb(url, body, new LLInventoryModelFetchItemResponder(body));
|
||||
approvement.honored();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -739,6 +746,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
|
||||
body["items"] = item_request_body_lib;
|
||||
|
||||
LLHTTPClient::post_nb(url, body, new LLInventoryModelFetchItemResponder(body));
|
||||
approvement.honored();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1276,6 +1276,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
|
||||
{
|
||||
return false ; //wait.
|
||||
}
|
||||
// If AIPerService::wantsMoreHTTPRequestsFor returns true then it approved ONE request.
|
||||
// This object keeps track of whether or not that is honored.
|
||||
AIPerService::Approvement approvement(mPerServicePtr);
|
||||
|
||||
mFetcher->removeFromNetworkQueue(this, false);
|
||||
|
||||
@@ -1322,6 +1325,8 @@ bool LLTextureFetchWorker::doWork(S32 param)
|
||||
LLHTTPClient::request(mUrl, LLHTTPClient::HTTP_GET, NULL,
|
||||
new HTTPGetResponder(mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, mRequestedOffset, true),
|
||||
headers/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, no_does_authentication, allow_compressed_reply, NULL, 0, NULL, false);
|
||||
// Now the request was added to the command queue.
|
||||
approvement.honored();
|
||||
res = true;
|
||||
}
|
||||
if (!res)
|
||||
|
||||
Reference in New Issue
Block a user