diff options
author | willchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-04 17:12:48 +0000 |
---|---|---|
committer | willchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-04 17:12:48 +0000 |
commit | fadca57773a35311b287a159fb1e0e62e22d5ccc (patch) | |
tree | 7809e2b2d236b7f0d3e76d9928d457d96872eeef | |
parent | 8568d97d7e4b58029613618e9dcd2c8771238be6 (diff) | |
download | chromium_src-fadca57773a35311b287a159fb1e0e62e22d5ccc.zip chromium_src-fadca57773a35311b287a159fb1e0e62e22d5ccc.tar.gz chromium_src-fadca57773a35311b287a159fb1e0e62e22d5ccc.tar.bz2 |
Fix purify freeze. Revert "Use a priority queue to assure that subresources are resolved asap"
This reverts git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17605 0039d316-1c4b-4281-b951-d872f2087c98
TBR=jar
Review URL: http://codereview.chromium.org/118239
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17638 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/net/dns_host_info.cc | 23 | ||||
-rw-r--r-- | chrome/browser/net/dns_host_info.h | 16 | ||||
-rw-r--r-- | chrome/browser/net/dns_host_info_unittest.cc | 41 | ||||
-rw-r--r-- | chrome/browser/net/dns_master.cc | 83 | ||||
-rw-r--r-- | chrome/browser/net/dns_master.h | 54 | ||||
-rw-r--r-- | chrome/browser/net/dns_master_unittest.cc | 63 |
6 files changed, 24 insertions, 256 deletions
diff --git a/chrome/browser/net/dns_host_info.cc b/chrome/browser/net/dns_host_info.cc index dbfde3b..d40acd7 100644 --- a/chrome/browser/net/dns_host_info.cc +++ b/chrome/browser/net/dns_host_info.cc @@ -77,7 +77,6 @@ void DnsHostInfo::set_cache_expiration(TimeDelta time) { void DnsHostInfo::SetQueuedState(ResolutionMotivation motivation) { DCHECK(PENDING == state_ || FOUND == state_ || NO_SUCH_NAME == state_); - old_prequeue_state_ = state_; state_ = QUEUED; queue_duration_ = resolve_duration_ = kNullDuration; SetMotivation(motivation); @@ -93,24 +92,6 @@ void DnsHostInfo::SetAssignedState() { UMA_HISTOGRAM_TIMES("DNS.PrefetchQueue", queue_duration_); } -void DnsHostInfo::RemoveFromQueue() { - DCHECK(ASSIGNED == state_); - state_ = old_prequeue_state_; - DLogResultsStats("DNS Prefetch reset to prequeue"); - static const TimeDelta kBoundary = TimeDelta::FromSeconds(2); - if (queue_duration_ > kBoundary) { - UMA_HISTOGRAM_MEDIUM_TIMES("DNS.QueueRecycledDeltaOver2", - queue_duration_ - kBoundary); - return; - } - // Make a custom linear histogram for the region from 0 to boundary. - const size_t kBucketCount = 52; - static LinearHistogram histogram("DNS.QueueRecycledUnder2", TimeDelta(), - kBoundary, kBucketCount); - histogram.SetFlags(kUmaTargetedHistogramFlag); - histogram.AddTime(queue_duration_); -} - void DnsHostInfo::SetPendingDeleteState() { DCHECK(ASSIGNED == state_ || ASSIGNED_BUT_MARKED == state_); state_ = ASSIGNED_BUT_MARKED; @@ -162,7 +143,7 @@ void DnsHostInfo::SetFinishedState(bool was_resolved) { void DnsHostInfo::SetHostname(const std::string& hostname) { if (hostname != hostname_) { - DCHECK_EQ(hostname_.size(), 0u); // Not yet initialized. + DCHECK(hostname_.size() == 0); // Not yet initialized. hostname_ = hostname; } } @@ -190,7 +171,7 @@ bool DnsHostInfo::IsStillCached() const { DnsBenefit DnsHostInfo::AccruePrefetchBenefits(DnsHostInfo* navigation_info) { DCHECK(FINISHED == navigation_info->state_ || FINISHED_UNRESOLVED == navigation_info->state_); - DCHECK_EQ(navigation_info->hostname_, hostname_.data()); + DCHECK(0 == navigation_info->hostname_.compare(hostname_.data())); if ((0 == benefits_remaining_.InMilliseconds()) || (FOUND != state_ && NO_SUCH_NAME != state_)) { diff --git a/chrome/browser/net/dns_host_info.h b/chrome/browser/net/dns_host_info.h index 34160d5..5ffca75 100644 --- a/chrome/browser/net/dns_host_info.h +++ b/chrome/browser/net/dns_host_info.h @@ -52,11 +52,11 @@ class DnsHostInfo { enum DnsProcessingState { // When processed by our prefetching system, the states are: PENDING, // Constructor has completed. - QUEUED, // In name queue but not yet being resolved. - ASSIGNED, // Being resolved (or being reset to earlier state) + QUEUED, // In prefetch queue but not yet being resolved. + ASSIGNED, // Currently being processed. ASSIGNED_BUT_MARKED, // Needs to be deleted as soon as it's resolved. - FOUND, // DNS resolution completed. - NO_SUCH_NAME, // DNS resolution completed. + FOUND, // DNS prefetch search completed. + NO_SUCH_NAME, // DNS prefetch search completed. // When processed by the network stack during navigation, the states are: STARTED, // Resolution has begun for a navigation. FINISHED, // Resolution has completed for a navigation. @@ -74,7 +74,6 @@ class DnsHostInfo { // initializing of the DnsMaster's map (of info for Hostnames). DnsHostInfo() : state_(PENDING), - old_prequeue_state_(state_), resolve_duration_(kNullDuration), queue_duration_(kNullDuration), benefits_remaining_(), @@ -96,7 +95,6 @@ class DnsHostInfo { // The prefetching lifecycle. void SetQueuedState(ResolutionMotivation motivation); void SetAssignedState(); - void RemoveFromQueue(); void SetPendingDeleteState(); void SetFoundState(); void SetNoSuchNameState(); @@ -159,13 +157,7 @@ class DnsHostInfo { // The next declaration is non-const to facilitate testing. static base::TimeDelta kCacheExpirationDuration; - // The current state of this instance. DnsProcessingState state_; - - // Record the state prior to going to a queued state, in case we have to back - // out of the queue. - DnsProcessingState old_prequeue_state_; - std::string hostname_; // Hostname for this info. // When was last state changed (usually lookup completed). diff --git a/chrome/browser/net/dns_host_info_unittest.cc b/chrome/browser/net/dns_host_info_unittest.cc index 87f64bc..2c50236 100644 --- a/chrome/browser/net/dns_host_info_unittest.cc +++ b/chrome/browser/net/dns_host_info_unittest.cc @@ -82,47 +82,6 @@ TEST(DnsHostInfoTest, StateChangeTest) { EXPECT_TRUE(info.NeedsDnsUpdate(hostname1)) << "expiration time not honored"; } -// When a system gets "congested" relative to DNS, it means it is doing too many -// DNS resolutions, and bogging down the system. When we detect such a -// situation, we divert the sequence of states a DnsHostInfo instance moves -// through. Rather than proceeding from QUEUED (waiting in a name queue for a -// worker thread that can resolve the name) to ASSIGNED (where a worker thread -// actively resolves the name), we enter the ASSIGNED state (without actually -// getting sent to a resolver thread) and reset our state to what it was before -// the corresponding name was put in the work_queue_. This test drives through -// the state transitions used in such congestion handling. -TEST(DnsHostInfoTest, CongestionResetStateTest) { - DnsHostInfo info; - std::string hostname1("domain1.com"); - - info.SetHostname(hostname1); - info.SetQueuedState(DnsHostInfo::UNIT_TEST_MOTIVATED); - info.SetAssignedState(); - EXPECT_TRUE(info.is_assigned()); - - info.RemoveFromQueue(); // Do the reset. - EXPECT_FALSE(info.is_assigned()); - - // Since this was a new info instance, and it never got resolved, we land back - // in a PENDING state rather than FOUND or NO_SUCH_NAME. - EXPECT_FALSE(info.was_found()); - EXPECT_FALSE(info.was_nonexistant()); - - // Make sure we're completely re-usable, by going throug a normal flow. - info.SetQueuedState(DnsHostInfo::UNIT_TEST_MOTIVATED); - info.SetAssignedState(); - info.SetFoundState(); - EXPECT_TRUE(info.was_found()); - - // Use the congestion flow, and check that we end up in the found state. - info.SetQueuedState(DnsHostInfo::UNIT_TEST_MOTIVATED); - info.SetAssignedState(); - info.RemoveFromQueue(); // Do the reset. - EXPECT_FALSE(info.is_assigned()); - EXPECT_TRUE(info.was_found()); // Back to what it was before being queued. -} - - // TODO(jar): Add death test for illegal state changes, and also for setting // hostname when already set. diff --git a/chrome/browser/net/dns_master.cc b/chrome/browser/net/dns_master.cc index 74fb9e5..bbb450a 100644 --- a/chrome/browser/net/dns_master.cc +++ b/chrome/browser/net/dns_master.cc @@ -360,24 +360,23 @@ DnsHostInfo* DnsMaster::PreLockedResolve( } info->SetQueuedState(motivation); - work_queue_.Push(hostname, motivation); + name_buffer_.push(hostname); + PreLockedScheduleLookups(); + return info; } void DnsMaster::PreLockedScheduleLookups() { - while (!work_queue_.IsEmpty() && + while (!name_buffer_.empty() && pending_lookups_.size() < max_concurrent_lookups_) { - const std::string hostname(work_queue_.Pop()); + const std::string hostname(name_buffer_.front()); + name_buffer_.pop(); + DnsHostInfo* info = &results_[hostname]; DCHECK(info->HasHostname(hostname)); info->SetAssignedState(); - if (PreLockedCongestionControlPerformed(info)) { - DCHECK(work_queue_.IsEmpty()); - return; - } - LookupRequest* request = new LookupRequest(this, hostname); if (request->Start()) { pending_lookups_.insert(request); @@ -390,33 +389,14 @@ void DnsMaster::PreLockedScheduleLookups() { } } -bool DnsMaster::PreLockedCongestionControlPerformed(DnsHostInfo* info) { - // Note: queue_duration is ONLY valid after we go to assigned state. - // TODO(jar): Tune selection of arbitrary 1 second constant. Add plumbing so - // that this can be set as part of an A/B experiment. - if (info->queue_duration() < base::TimeDelta::FromSeconds(1)) - return false; - // We need to discard all entries in our queue, as we're keeping them waiting - // too long. By doing this, we'll have a chance to quickly service urgent - // resolutions, and not have a bogged down system. - while (true) { - info->RemoveFromQueue(); - if (work_queue_.IsEmpty()) - break; - info = &results_[work_queue_.Pop()]; - info->SetAssignedState(); - } - return true; -} - void DnsMaster::OnLookupFinished(LookupRequest* request, const std::string& hostname, bool found) { AutoLock auto_lock(lock_); // For map access (changing info values). DnsHostInfo* info = &results_[hostname]; DCHECK(info->HasHostname(hostname)); - if (info->is_marked_to_delete()) { + if (info->is_marked_to_delete()) results_.erase(hostname); - } else { + else { if (found) info->SetFoundState(); else @@ -438,9 +418,10 @@ void DnsMaster::DiscardAllResults() { // Try to delete anything in our work queue. - while (!work_queue_.IsEmpty()) { + while (!name_buffer_.empty()) { // Emulate processing cycle as though host was not found. - std::string hostname = work_queue_.Pop(); + std::string hostname = name_buffer_.front(); + name_buffer_.pop(); DnsHostInfo* info = &results_[hostname]; DCHECK(info->HasHostname(hostname)); info->SetAssignedState(); @@ -516,44 +497,4 @@ void DnsMaster::DeserializeReferrers(const ListValue& referral_list) { } } - -//------------------------------------------------------------------------------ - -DnsMaster::HostNameQueue::HostNameQueue() { -} - -DnsMaster::HostNameQueue::~HostNameQueue() { -} - -void DnsMaster::HostNameQueue::Push(const std::string& hostname, - DnsHostInfo::ResolutionMotivation motivation) { - switch (motivation) { - case DnsHostInfo::STATIC_REFERAL_MOTIVATED: - case DnsHostInfo::LEARNED_REFERAL_MOTIVATED: - case DnsHostInfo::MOUSE_OVER_MOTIVATED: - rush_queue_.push(hostname); - break; - - default: - background_queue_.push(hostname); - break; - } -} - -bool DnsMaster::HostNameQueue::IsEmpty() const { - return rush_queue_.empty() && background_queue_.empty(); -} - -std::string DnsMaster::HostNameQueue::Pop() { - DCHECK(!IsEmpty()); - if (!rush_queue_.empty()) { - std::string hostname(rush_queue_.front()); - rush_queue_.pop(); - return hostname; - } - std::string hostname(background_queue_.front()); - background_queue_.pop(); - return hostname; -} - } // namespace chrome_browser_net diff --git a/chrome/browser/net/dns_master.h b/chrome/browser/net/dns_master.h index a78e061..5dfb968 100644 --- a/chrome/browser/net/dns_master.h +++ b/chrome/browser/net/dns_master.h @@ -33,7 +33,7 @@ typedef std::map<std::string, DnsHostInfo> Results; class DnsMaster { public: // Specify how many concurrent (paralell) prefetches will be performed. - explicit DnsMaster(size_t max_concurrent); + DnsMaster(size_t max_concurrent); ~DnsMaster(); // Cancel pending requests and prevent new ones from being made. @@ -93,39 +93,10 @@ class DnsMaster { FRIEND_TEST(DnsMasterTest, SingleLookupTest); FRIEND_TEST(DnsMasterTest, ConcurrentLookupTest); FRIEND_TEST(DnsMasterTest, MassiveConcurrentLookupTest); - FRIEND_TEST(DnsMasterTest, PriorityQueuePushPopTest); - FRIEND_TEST(DnsMasterTest, PriorityQueueReorderTest); friend class WaitForResolutionHelper; // For testing. class LookupRequest; - // A simple priority queue for handling host names. - // Some names that are queued up have |motivation| that requires very rapid - // handling. For example, a sub-resource name lookup MUST be done before the - // actual sub-resource is fetched. In contrast, a name that was speculatively - // noted in a page has to be resolved before the user "gets around to" - // clicking on a link. By tagging (with a motivation) each push we make into - // this FIFO queue, the queue can re-order the more important names to service - // them sooner (relative to some low priority background resolutions). - class HostNameQueue { - public: - HostNameQueue(); - ~HostNameQueue(); - void Push(const std::string& hostname, - DnsHostInfo::ResolutionMotivation motivation); - bool IsEmpty() const; - std::string Pop(); - - private: - // The names in the queue that should be serviced (popped) ASAP. - std::queue<std::string> rush_queue_; - // The names in the queue that should only be serviced when rush_queue is - // empty. - std::queue<std::string> background_queue_; - - DISALLOW_COPY_AND_ASSIGN(HostNameQueue); - }; - // A map that is keyed with the hostnames that we've learned were the cause // of loading additional hostnames. The list of additional hostnames in held // in a Referrer instance, which is found in this type. @@ -162,29 +133,16 @@ class DnsMaster { DnsHostInfo* PreLockedResolve(const std::string& hostname, DnsHostInfo::ResolutionMotivation motivation); - // Check to see if too much queuing delay has been noted for the given info, - // which indicates that there is "congestion" or growing delay in handling the - // resolution of names. Rather than letting this congestion potentially grow - // without bounds, we abandon our queued efforts at pre-resolutions in such a - // case. - // To do this, we will recycle |info|, as well as all queued items, back to - // the state they had before they were queued up. We can't do anything about - // the resolutions we've already sent off for processing on another thread, so - // we just let them complete. On a slow system, subject to congestion, this - // will greatly reduce the number of resolutions done, but it will assure that - // any resolutions that are done, are in a timely and hence potentially - // helpful manner. - bool PreLockedCongestionControlPerformed(DnsHostInfo* info); - - // Take lookup requests from work_queue_ and tell HostResolver to look them up - // asynchronously, provided we don't exceed concurrent resolution limit. + // Take lookup requests from name_buffer_ and tell HostResolver + // to look them up asynchronously, provided we don't exceed + // concurrent resolution limit. void PreLockedScheduleLookups(); // Synchronize access to variables listed below. Lock lock_; - // work_queue_ holds a list of names we need to look up. - HostNameQueue work_queue_; + // name_buffer_ holds a list of names we need to look up. + std::queue<std::string> name_buffer_; // results_ contains information for existing/prior prefetches. Results results_; diff --git a/chrome/browser/net/dns_master_unittest.cc b/chrome/browser/net/dns_master_unittest.cc index b6805f5..2285229 100644 --- a/chrome/browser/net/dns_master_unittest.cc +++ b/chrome/browser/net/dns_master_unittest.cc @@ -541,67 +541,4 @@ TEST_F(DnsMasterTest, ReferrerSerializationTrimTest) { master.Shutdown(); } - -TEST_F(DnsMasterTest, PriorityQueuePushPopTest) { - DnsMaster::HostNameQueue queue; - - // First check high priority queue FIFO functionality. - EXPECT_TRUE(queue.IsEmpty()); - queue.Push("a", DnsHostInfo::LEARNED_REFERAL_MOTIVATED); - EXPECT_FALSE(queue.IsEmpty()); - queue.Push("b", DnsHostInfo::MOUSE_OVER_MOTIVATED); - EXPECT_FALSE(queue.IsEmpty()); - EXPECT_EQ(queue.Pop(), "a"); - EXPECT_FALSE(queue.IsEmpty()); - EXPECT_EQ(queue.Pop(), "b"); - EXPECT_TRUE(queue.IsEmpty()); - - // Then check low priority queue FIFO functionality. - queue.IsEmpty(); - queue.Push("a", DnsHostInfo::PAGE_SCAN_MOTIVATED); - EXPECT_FALSE(queue.IsEmpty()); - queue.Push("b", DnsHostInfo::OMNIBOX_MOTIVATED); - EXPECT_FALSE(queue.IsEmpty()); - EXPECT_EQ(queue.Pop(), "a"); - EXPECT_FALSE(queue.IsEmpty()); - EXPECT_EQ(queue.Pop(), "b"); - EXPECT_TRUE(queue.IsEmpty()); -} - -TEST_F(DnsMasterTest, PriorityQueueReorderTest) { - DnsMaster::HostNameQueue queue; - - // Push all the low priority items. - EXPECT_TRUE(queue.IsEmpty()); - queue.Push("scan", DnsHostInfo::PAGE_SCAN_MOTIVATED); - queue.Push("unit", DnsHostInfo::UNIT_TEST_MOTIVATED); - queue.Push("lmax", DnsHostInfo::LINKED_MAX_MOTIVATED); - queue.Push("omni", DnsHostInfo::OMNIBOX_MOTIVATED); - queue.Push("startup", DnsHostInfo::STARTUP_LIST_MOTIVATED); - queue.Push("omni", DnsHostInfo::OMNIBOX_MOTIVATED); - - // Push all the high prority items - queue.Push("learned", DnsHostInfo::LEARNED_REFERAL_MOTIVATED); - queue.Push("refer", DnsHostInfo::STATIC_REFERAL_MOTIVATED); - queue.Push("mouse", DnsHostInfo::MOUSE_OVER_MOTIVATED); - - // Check that high priority stuff comes out first, and in FIFO order. - EXPECT_EQ(queue.Pop(), "learned"); - EXPECT_EQ(queue.Pop(), "refer"); - EXPECT_EQ(queue.Pop(), "mouse"); - - // ...and then low priority strings. - EXPECT_EQ(queue.Pop(), "scan"); - EXPECT_EQ(queue.Pop(), "unit"); - EXPECT_EQ(queue.Pop(), "lmax"); - EXPECT_EQ(queue.Pop(), "omni"); - EXPECT_EQ(queue.Pop(), "startup"); - EXPECT_EQ(queue.Pop(), "omni"); - - EXPECT_TRUE(queue.IsEmpty()); -} - - - - } // namespace chrome_browser_net |