WIP: Added AIPerService::Approvement

This commit is contained in:
Aleric Inglewood
2013-05-07 19:36:10 +02:00
parent e3fec7c715
commit 5b1984ed0c
6 changed files with 58 additions and 4 deletions

View File

@@ -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--;
}
}

View File

@@ -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&);

View File

@@ -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));
}

View File

@@ -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>

View File

@@ -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();
}
}
}

View File

@@ -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)