Bug 1478732 - Change nsHostResolver to dispatch one resolver task per native lookup r=bagder

Differential Revision: https://phabricator.services.mozilla.com/D2431

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Valentin Gosu 2018-08-07 07:03:57 +00:00
Родитель 0a42678142
Коммит 1030589ee4
3 изменённых файлов: 35 добавлений и 112 удалений

Просмотреть файл

@ -2088,7 +2088,7 @@ pref("network.dns.offline-localhost", true);
// Defines how much longer resolver threads should stay idle before are shut down.
// A negative value will keep the thread alive forever.
pref("network.dns.resolver-thread-extra-idle-time-seconds", 60);
pref("network.dns.resolver-thread-extra-idle-time-seconds", -1);
// The maximum allowed length for a URL - 1MB default
pref("network.standard-url.max-length", 1048576);

Просмотреть файл

@ -548,10 +548,8 @@ nsHostResolver::nsHostResolver(uint32_t maxCacheEntries,
, mDefaultCacheLifetime(defaultCacheEntryLifetime)
, mDefaultGracePeriod(defaultGracePeriod)
, mLock("nsHostResolver.mLock")
, mIdleTaskCV(mLock, "nsHostResolver.mIdleTaskCV")
, mEvictionQSize(0)
, mShutdown(true)
, mNumIdleTasks(0)
, mActiveTaskCount(0)
, mActiveAnyThreadCount(0)
, mPendingCount(0)
@ -605,7 +603,7 @@ nsHostResolver::Init()
#endif
// We can configure the threadpool to keep threads alive for a while after
// the last ThreadFunc task has been executed.
// the last ResolveHostTask has been executed.
int32_t poolTimeoutSecs = Preferences::GetInt(kPrefThreadIdleTime, 60);
uint32_t poolTimeoutMs;
if (poolTimeoutSecs < 0) {
@ -707,9 +705,6 @@ nsHostResolver::Shutdown()
mEvictionQSize = 0;
mPendingCount = 0;
if (mNumIdleTasks)
mIdleTaskCV.NotifyAll();
// empty host database
mRecordDB.Clear();
}
@ -1016,7 +1011,6 @@ nsHostResolver::ResolveHost(const nsACString &aHost,
rec->remove();
mHighQ.insertBack(rec);
rec->flags = flags;
ConditionallyCreateThread(rec);
} else if (IsMediumPriority(flags) &&
IsLowPriority(rec->flags)) {
// Move from low to med.
@ -1024,7 +1018,6 @@ nsHostResolver::ResolveHost(const nsACString &aHost,
rec->remove();
mMediumQ.insertBack(rec);
rec->flags = flags;
mIdleTaskCV.Notify();
}
}
}
@ -1083,31 +1076,6 @@ nsHostResolver::DetachCallback(const nsACString &host,
}
}
nsresult
nsHostResolver::ConditionallyCreateThread(nsHostRecord *rec)
{
if (mNumIdleTasks) {
// wake up idle tasks to process this lookup
mIdleTaskCV.Notify();
}
else if ((mActiveTaskCount < HighThreadThreshold) ||
(IsHighPriority(rec->flags) && mActiveTaskCount < MAX_RESOLVER_THREADS)) {
nsCOMPtr<nsIRunnable> event =
mozilla::NewRunnableMethod("nsHostResolver::ThreadFunc",
this,
&nsHostResolver::ThreadFunc);
mActiveTaskCount++;
nsresult rv = mResolverThreads->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
if (NS_FAILED(rv)) {
mActiveTaskCount--;
}
}
else {
LOG((" Unable to find a thread for looking up host [%s].\n", rec->host.get()));
}
return NS_OK;
}
// make sure the mTrrLock is held when this is used!
#define TRROutstanding() ((rec->mTrrA || rec->mTrrAAAA))
@ -1247,15 +1215,16 @@ nsHostResolver::NativeLookup(nsHostRecord *aRec)
rec->onQueue = true;
rec->mResolving++;
nsresult rv = ConditionallyCreateThread(rec);
LOG ((" DNS thread counters: total=%d any-live=%d idle=%d pending=%d\n",
LOG ((" DNS thread counters: total=%d any-live=%d pending=%d\n",
static_cast<uint32_t>(mActiveTaskCount),
static_cast<uint32_t>(mActiveAnyThreadCount),
static_cast<uint32_t>(mNumIdleTasks),
static_cast<uint32_t>(mPendingCount)));
return rv;
nsCOMPtr<nsIRunnable> event =
mozilla::NewRunnableMethod("nsHostResolver::ResolveHostTask",
this,
&nsHostResolver::ResolveHostTask);
return mResolverThreads->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
}
ResolverMode
@ -1340,73 +1309,34 @@ nsHostResolver::DeQueue(LinkedList<RefPtr<nsHostRecord>>& aQ, nsHostRecord **aRe
bool
nsHostResolver::GetHostToLookup(nsHostRecord **result)
{
bool timedOut = false;
TimeDuration timeout;
TimeStamp epoch, now;
MutexAutoLock lock(mLock);
timeout = (mNumIdleTasks >= HighThreadThreshold) ? mShortIdleTimeout : mLongIdleTimeout;
epoch = TimeStamp::Now();
while (!mShutdown) {
// remove next record from Q; hand over owning reference. Check high, then med, then low
#define SET_GET_TTL(var, val) (var)->mGetTtl = sGetTtlEnabled && (val)
if (!mHighQ.isEmpty()) {
DeQueue (mHighQ, result);
SET_GET_TTL(*result, false);
if (!mHighQ.isEmpty()) {
DeQueue(mHighQ, result);
SET_GET_TTL(*result, false);
return true;
}
if (mActiveAnyThreadCount < HighThreadThreshold) {
if (!mMediumQ.isEmpty()) {
DeQueue(mMediumQ, result);
mActiveAnyThreadCount++;
(*result)->usingAnyThread = true;
SET_GET_TTL(*result, true);
return true;
}
if (mActiveAnyThreadCount < HighThreadThreshold) {
if (!mMediumQ.isEmpty()) {
DeQueue (mMediumQ, result);
mActiveAnyThreadCount++;
(*result)->usingAnyThread = true;
SET_GET_TTL(*result, true);
return true;
}
if (!mLowQ.isEmpty()) {
DeQueue (mLowQ, result);
mActiveAnyThreadCount++;
(*result)->usingAnyThread = true;
SET_GET_TTL(*result, true);
return true;
}
}
// Determining timeout is racy, so allow one cycle through checking the queues
// before exiting.
if (timedOut)
break;
// wait for one or more of the following to occur:
// (1) the pending queue has a host record to process
// (2) the shutdown flag has been set
// (3) the thread has been idle for too long
mNumIdleTasks++;
mIdleTaskCV.Wait(timeout);
mNumIdleTasks--;
now = TimeStamp::Now();
if (now - epoch >= timeout) {
timedOut = true;
} else {
// It is possible that CondVar::Wait() was interrupted and returned
// early, in which case we will loop back and re-enter it. In that
// case we want to do so with the new timeout reduced to reflect
// time already spent waiting.
timeout -= now - epoch;
epoch = now;
if (!mLowQ.isEmpty()) {
DeQueue(mLowQ, result);
mActiveAnyThreadCount++;
(*result)->usingAnyThread = true;
SET_GET_TTL(*result, true);
return true;
}
}
// tell thread to exit...
return false;
}
@ -1826,8 +1756,9 @@ nsHostResolver::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const
}
void
nsHostResolver::ThreadFunc()
nsHostResolver::ResolveHostTask()
{
mActiveTaskCount++;
LOG(("DNS lookup thread - starting execution.\n"));
#if defined(RES_RETRY_ON_FAILURE)
@ -1836,17 +1767,12 @@ nsHostResolver::ThreadFunc()
RefPtr<nsHostRecord> rec;
AddrInfo *ai = nullptr;
do {
if (!rec) {
RefPtr<nsHostRecord> tmpRec;
if (!GetHostToLookup(getter_AddRefs(tmpRec))) {
break; // thread shutdown signal
}
// GetHostToLookup() returns an owning reference
MOZ_ASSERT(tmpRec);
rec.swap(tmpRec);
}
if (!GetHostToLookup(getter_AddRefs(rec))) {
NS_WARNING("Could not find any host to resolve");
return;
}
do {
LOG(("DNS lookup thread - Calling getaddrinfo for host [%s].\n",
rec->host.get()));
@ -1901,7 +1827,7 @@ nsHostResolver::ThreadFunc()
} else {
rec = nullptr;
}
} while(true);
} while(rec);
mActiveTaskCount--;
LOG(("DNS lookup thread - queue empty, task finished.\n"));

Просмотреть файл

@ -421,7 +421,6 @@ private:
// Cancels host records in the pending queue and also
// calls CompleteLookup with the NS_ERROR_ABORT result code.
void ClearPendingQueue(mozilla::LinkedList<RefPtr<nsHostRecord>>& aPendingQ);
nsresult ConditionallyCreateThread(nsHostRecord *rec);
/**
* Starts a new lookup in the background for entries that are in the grace
@ -429,7 +428,7 @@ private:
*/
nsresult ConditionallyRefreshRecord(nsHostRecord *rec, const nsACString &host);
void ThreadFunc();
void ResolveHostTask();
enum {
METHOD_HIT = 1,
@ -445,7 +444,6 @@ private:
uint32_t mDefaultCacheLifetime; // granularity seconds
uint32_t mDefaultGracePeriod; // granularity seconds
mutable Mutex mLock; // mutable so SizeOfIncludingThis can be const
CondVar mIdleTaskCV;
nsRefPtrHashtable<nsGenericHashKey<nsHostKey>, nsHostRecord> mRecordDB;
mozilla::LinkedList<RefPtr<nsHostRecord>> mHighQ;
mozilla::LinkedList<RefPtr<nsHostRecord>> mMediumQ;
@ -459,7 +457,6 @@ private:
RefPtr<nsIThreadPool> mResolverThreads;
mozilla::Atomic<bool> mShutdown;
mozilla::Atomic<uint32_t> mNumIdleTasks;
mozilla::Atomic<uint32_t> mActiveTaskCount;
mozilla::Atomic<uint32_t> mActiveAnyThreadCount;
mozilla::Atomic<uint32_t> mPendingCount;