SH-3244 Syscall avoidance in HttpRequest::update() method

Well, achieved that by doing work in bulk when needed.  But
turned into some additional things.  Change timebase from
mS to uS as, well, things are headed that way.  Implement
an HttpReplyQueue::fetchAll method (advertised one, hadn't
implemented it).
master
Monty Brandenberg 2012-07-10 18:50:21 -04:00
parent a5ba9c0eb3
commit bc72acbfd2
8 changed files with 92 additions and 53 deletions

View File

@ -84,4 +84,24 @@ HttpOperation * HttpReplyQueue::fetchOp()
return result;
}
void HttpReplyQueue::fetchAll(OpContainer & ops)
{
// Not valid putting something back on the queue...
llassert_always(ops.empty());
{
HttpScopedLock lock(mQueueMutex);
if (! mQueue.empty())
{
mQueue.swap(ops);
}
}
// Caller also acquires the reference counts on each op.
return;
}
} // end namespace LLCore

View File

@ -120,10 +120,9 @@ HttpOperation * HttpRequestQueue::fetchOp(bool wait)
void HttpRequestQueue::fetchAll(bool wait, OpContainer & ops)
{
// Note: Should probably test whether we're empty or not here.
// A target passed in with entries is likely also carrying
// reference counts and we're going to leak something.
ops.clear();
// Not valid putting something back on the queue...
llassert_always(ops.empty());
{
HttpScopedLock lock(mQueueMutex);

View File

@ -244,7 +244,7 @@ int main(int argc, char** argv)
int passes(0);
while (! ws.reload(hr))
{
hr->update(5000);
hr->update(5000000);
ms_sleep(2);
if (0 == (++passes % 200))
{

View File

@ -296,17 +296,43 @@ HttpHandle HttpRequest::requestNoOp(HttpHandler * user_handler)
}
HttpStatus HttpRequest::update(long millis)
HttpStatus HttpRequest::update(long usecs)
{
const HttpTime limit(totalTime() + (1000 * HttpTime(millis)));
HttpOperation * op(NULL);
while (limit >= totalTime() && (op = mReplyQueue->fetchOp()))
if (usecs)
{
// Process operation
op->visitNotifier(this);
const HttpTime limit(totalTime() + HttpTime(usecs));
while (limit >= totalTime() && (op = mReplyQueue->fetchOp()))
{
// Process operation
op->visitNotifier(this);
// We're done with the operation
op->release();
// We're done with the operation
op->release();
}
}
else
{
// Same as above, just no time limit
HttpReplyQueue::OpContainer replies;
mReplyQueue->fetchAll(replies);
if (! replies.empty())
{
for (HttpReplyQueue::OpContainer::iterator iter(replies.begin());
replies.end() != iter;
++iter)
{
// Swap op pointer for NULL;
op = *iter; *iter = NULL;
// Process operation
op->visitNotifier(this);
// We're done with the operation
op->release();
}
}
}
return HttpStatus();

View File

@ -341,13 +341,14 @@ public:
/// are expected to return 'quickly' and do any significant processing
/// outside of the notification callback to onCompleted().
///
/// @param millis Maximum number of wallclock milliseconds to
/// @param usecs Maximum number of wallclock microseconds to
/// spend in the call. As hinted at above, this
/// is partly a function of application code so it's
/// a soft limit.
/// a soft limit. A '0' value will run without
/// time limit.
///
/// @return Standard status code.
HttpStatus update(long millis);
HttpStatus update(long usecs);
/// @}

View File

@ -260,7 +260,7 @@ void HttpRequestTestObjectType::test<3>()
int limit(20);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000);
req->update(1000000);
usleep(100000);
}
ensure("Request executed in reasonable time", count < limit);
@ -275,7 +275,7 @@ void HttpRequestTestObjectType::test<3>()
limit = 100;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000);
req->update(1000000);
usleep(100000);
}
ensure("Second request executed in reasonable time", count < limit);
@ -358,8 +358,8 @@ void HttpRequestTestObjectType::test<4>()
int limit(20);
while (count++ < limit && mHandlerCalls < 2)
{
req1->update(1000);
req2->update(1000);
req1->update(1000000);
req2->update(1000000);
usleep(100000);
}
ensure("Request executed in reasonable time", count < limit);
@ -375,8 +375,8 @@ void HttpRequestTestObjectType::test<4>()
limit = 100;
while (count++ < limit && mHandlerCalls < 3)
{
req1->update(1000);
req2->update(1000);
req1->update(1000000);
req2->update(1000000);
usleep(100000);
}
ensure("Second request executed in reasonable time", count < limit);
@ -459,7 +459,7 @@ void HttpRequestTestObjectType::test<5>()
int limit(10);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000);
req->update(1000000);
usleep(100000);
}
ensure("NoOp notification received", mHandlerCalls == 1);
@ -535,7 +535,7 @@ void HttpRequestTestObjectType::test<6>()
int limit(10);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000);
req->update(1000000);
usleep(100000);
}
ensure("No notifications received", mHandlerCalls == 0);
@ -616,7 +616,7 @@ void HttpRequestTestObjectType::test<7>()
int limit(50); // With one retry, should fail quickish
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000);
req->update(1000000);
usleep(100000);
}
ensure("Request executed in reasonable time", count < limit);
@ -632,7 +632,7 @@ void HttpRequestTestObjectType::test<7>()
limit = 100;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000);
req->update(1000000);
usleep(100000);
}
ensure("Second request executed in reasonable time", count < limit);
@ -733,7 +733,7 @@ void HttpRequestTestObjectType::test<8>()
int limit(10);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000);
req->update(1000000);
usleep(100000);
}
ensure("Request executed in reasonable time", count < limit);
@ -749,7 +749,7 @@ void HttpRequestTestObjectType::test<8>()
limit = 10;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000);
req->update(1000000);
usleep(100000);
}
ensure("Second request executed in reasonable time", count < limit);
@ -843,7 +843,7 @@ void HttpRequestTestObjectType::test<9>()
int limit(10);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000);
req->update(1000000);
usleep(100000);
}
ensure("Request executed in reasonable time", count < limit);
@ -859,7 +859,7 @@ void HttpRequestTestObjectType::test<9>()
limit = 10;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000);
req->update(1000000);
usleep(100000);
}
ensure("Second request executed in reasonable time", count < limit);
@ -955,7 +955,7 @@ void HttpRequestTestObjectType::test<10>()
int limit(10);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000);
req->update(1000000);
usleep(100000);
}
ensure("Request executed in reasonable time", count < limit);
@ -971,7 +971,7 @@ void HttpRequestTestObjectType::test<10>()
limit = 10;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000);
req->update(1000000);
usleep(100000);
}
ensure("Second request executed in reasonable time", count < limit);
@ -1074,7 +1074,7 @@ void HttpRequestTestObjectType::test<11>()
int limit(10);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000);
req->update(1000000);
usleep(100000);
}
ensure("Request executed in reasonable time", count < limit);
@ -1090,7 +1090,7 @@ void HttpRequestTestObjectType::test<11>()
limit = 10;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000);
req->update(1000000);
usleep(100000);
}
ensure("Second request executed in reasonable time", count < limit);
@ -1194,7 +1194,7 @@ void HttpRequestTestObjectType::test<12>()
int limit(10);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000);
req->update(1000000);
usleep(100000);
}
ensure("Request executed in reasonable time", count < limit);
@ -1210,7 +1210,7 @@ void HttpRequestTestObjectType::test<12>()
limit = 10;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000);
req->update(1000000);
usleep(100000);
}
ensure("Second request executed in reasonable time", count < limit);
@ -1316,7 +1316,7 @@ void HttpRequestTestObjectType::test<13>()
int limit(10);
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000);
req->update(1000000);
usleep(100000);
}
ensure("Request executed in reasonable time", count < limit);
@ -1333,7 +1333,7 @@ void HttpRequestTestObjectType::test<13>()
limit = 10;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000);
req->update(1000000);
usleep(100000);
}
ensure("Second request executed in reasonable time", count < limit);
@ -1435,7 +1435,7 @@ void HttpRequestTestObjectType::test<14>()
int limit(50); // With one retry, should fail quickish
while (count++ < limit && mHandlerCalls < 1)
{
req->update(1000);
req->update(1000000);
usleep(100000);
}
ensure("Request executed in reasonable time", count < limit);
@ -1451,7 +1451,7 @@ void HttpRequestTestObjectType::test<14>()
limit = 100;
while (count++ < limit && mHandlerCalls < 2)
{
req->update(1000);
req->update(1000000);
usleep(100000);
}
ensure("Second request executed in reasonable time", count < limit);

View File

@ -5398,7 +5398,7 @@ void CoreHttp::cleanup()
{
while (! mStopped && LLTimer::getTotalSeconds() < (mStopRequested + MAX_THREAD_WAIT_TIME))
{
mRequest->update(200);
mRequest->update(200000);
ms_sleep(50);
}
if (! mStopped)

View File

@ -2740,22 +2740,14 @@ void LLTextureFetch::commonUpdate()
// Run a cross-thread command, if any.
cmdDoWork();
// Update Curl on same thread as mCurlGetRequest was constructed
LLCore::HttpStatus status = mHttpRequest->update(200);
// Deliver all completion notifications
LLCore::HttpStatus status = mHttpRequest->update(0);
if (! status)
{
LL_INFOS_ONCE("Texture") << "Problem during HTTP servicing. Reason: "
<< status.toString()
<< LL_ENDL;
}
#if 0
// *FIXME: maybe implement this another way...
if (processed > 0)
{
lldebugs << "processed: " << processed << " messages." << llendl;
}
#endif
}
@ -2840,7 +2832,8 @@ void LLTextureFetch::endThread()
void LLTextureFetch::threadedUpdate()
{
llassert_always(mHttpRequest);
#if 0
// Limit update frequency
const F32 PROCESS_TIME = 0.05f;
static LLFrameTimer process_timer;
@ -2849,9 +2842,10 @@ void LLTextureFetch::threadedUpdate()
return;
}
process_timer.reset();
#endif
commonUpdate();
#if 0
const F32 INFO_TIME = 1.0f;
static LLFrameTimer info_timer;
@ -2865,7 +2859,6 @@ void LLTextureFetch::threadedUpdate()
}
}
#endif
}
//////////////////////////////////////////////////////////////////////////////