Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(872)

Side by Side Diff: chrome/browser/predictors/loading_predictor.cc

Issue 2928033003: predictors: move ResourcePrefetcher handling to LoadingPredictor. (Closed)
Patch Set: Address comment. Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/predictors/loading_predictor.h" 5 #include "chrome/browser/predictors/loading_predictor.h"
6 6
7 #include <vector>
8
7 #include "base/memory/ptr_util.h" 9 #include "base/memory/ptr_util.h"
8 #include "base/metrics/histogram_macros.h" 10 #include "base/metrics/histogram_macros.h"
9 #include "chrome/browser/predictors/loading_data_collector.h" 11 #include "chrome/browser/predictors/loading_data_collector.h"
10 #include "chrome/browser/predictors/loading_stats_collector.h" 12 #include "chrome/browser/predictors/loading_stats_collector.h"
11 #include "chrome/browser/predictors/resource_prefetch_common.h" 13 #include "chrome/browser/predictors/resource_prefetch_common.h"
12 #include "chrome/browser/predictors/resource_prefetch_predictor.h" 14 #include "chrome/browser/predictors/resource_prefetch_predictor.h"
13 15
14 namespace predictors { 16 namespace predictors {
15 17
16 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary; 18 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary;
17 19
18 LoadingPredictor::LoadingPredictor(const LoadingPredictorConfig& config, 20 LoadingPredictor::LoadingPredictor(const LoadingPredictorConfig& config,
19 Profile* profile) 21 Profile* profile)
20 : config_(config), 22 : config_(config),
21 profile_(profile), 23 profile_(profile),
22 resource_prefetch_predictor_( 24 resource_prefetch_predictor_(
23 base::MakeUnique<ResourcePrefetchPredictor>(config, profile)), 25 base::MakeUnique<ResourcePrefetchPredictor>(config, profile)),
24 stats_collector_(base::MakeUnique<LoadingStatsCollector>( 26 stats_collector_(base::MakeUnique<LoadingStatsCollector>(
25 resource_prefetch_predictor_.get(), 27 resource_prefetch_predictor_.get(),
26 config)), 28 config)),
27 loading_data_collector_(base::MakeUnique<LoadingDataCollector>( 29 loading_data_collector_(base::MakeUnique<LoadingDataCollector>(
28 resource_prefetch_predictor())), 30 resource_prefetch_predictor())),
31 observer_(nullptr),
29 weak_factory_(this) { 32 weak_factory_(this) {
30 resource_prefetch_predictor_->SetStatsCollector(stats_collector_.get()); 33 resource_prefetch_predictor_->SetStatsCollector(stats_collector_.get());
31 } 34 }
32 35
33 LoadingPredictor::~LoadingPredictor() = default; 36 LoadingPredictor::~LoadingPredictor() = default;
34 37
35 void LoadingPredictor::PrepareForPageLoad(const GURL& url, HintOrigin origin) { 38 void LoadingPredictor::PrepareForPageLoad(const GURL& url, HintOrigin origin) {
36 if (active_hints_.find(url) != active_hints_.end()) 39 if (active_hints_.find(url) != active_hints_.end())
37 return; 40 return;
38 ResourcePrefetchPredictor::Prediction prediction; 41 ResourcePrefetchPredictor::Prediction prediction;
39 if (!resource_prefetch_predictor_->GetPrefetchData(url, &prediction)) 42 if (!resource_prefetch_predictor_->GetPrefetchData(url, &prediction))
40 return; 43 return;
41 44
42 // To report hint durations. 45 // To report hint durations.
43 active_hints_.emplace(url, base::TimeTicks::Now()); 46 active_hints_.emplace(url, base::TimeTicks::Now());
44 47 MaybeAddPrefetch(url, prediction, origin);
45 if (config_.IsPrefetchingEnabledForOrigin(profile_, origin))
46 resource_prefetch_predictor_->StartPrefetching(url, prediction);
47 } 48 }
48 49
49 void LoadingPredictor::CancelPageLoadHint(const GURL& url) { 50 void LoadingPredictor::CancelPageLoadHint(const GURL& url) {
50 CancelActiveHint(active_hints_.find(url)); 51 CancelActiveHint(active_hints_.find(url));
51 } 52 }
52 53
53 void LoadingPredictor::StartInitialization() { 54 void LoadingPredictor::StartInitialization() {
54 resource_prefetch_predictor_->StartInitialization(); 55 resource_prefetch_predictor_->StartInitialization();
55 } 56 }
56 57
57 LoadingDataCollector* LoadingPredictor::loading_data_collector() { 58 LoadingDataCollector* LoadingPredictor::loading_data_collector() {
58 return loading_data_collector_.get(); 59 return loading_data_collector_.get();
59 } 60 }
60 61
61 ResourcePrefetchPredictor* LoadingPredictor::resource_prefetch_predictor() { 62 ResourcePrefetchPredictor* LoadingPredictor::resource_prefetch_predictor() {
62 return resource_prefetch_predictor_.get(); 63 return resource_prefetch_predictor_.get();
63 } 64 }
64 65
65 void LoadingPredictor::Shutdown() { 66 void LoadingPredictor::Shutdown() {
66 resource_prefetch_predictor_->Shutdown(); 67 resource_prefetch_predictor_->Shutdown();
68
69 std::vector<std::unique_ptr<ResourcePrefetcher>> prefetchers;
70 for (auto& kv : prefetches_)
71 prefetchers.push_back(std::move(kv.second.first));
72
73 // |prefetchers| must be destroyed on the IO thread.
74 content::BrowserThread::PostTask(
75 content::BrowserThread::IO, FROM_HERE,
76 base::BindOnce(
77 [](std::vector<std::unique_ptr<ResourcePrefetcher>> prefetchers) {},
78 std::move(prefetchers)));
67 } 79 }
68 80
69 void LoadingPredictor::OnMainFrameRequest(const URLRequestSummary& summary) { 81 void LoadingPredictor::OnMainFrameRequest(const URLRequestSummary& summary) {
70 DCHECK(summary.resource_type == content::RESOURCE_TYPE_MAIN_FRAME); 82 DCHECK(summary.resource_type == content::RESOURCE_TYPE_MAIN_FRAME);
71 83
72 const NavigationID& navigation_id = summary.navigation_id; 84 const NavigationID& navigation_id = summary.navigation_id;
73 CleanupAbandonedHintsAndNavigations(navigation_id); 85 CleanupAbandonedHintsAndNavigations(navigation_id);
74 active_navigations_.emplace(navigation_id, navigation_id.main_frame_url); 86 active_navigations_.emplace(navigation_id, navigation_id.main_frame_url);
75 PrepareForPageLoad(navigation_id.main_frame_url, HintOrigin::NAVIGATION); 87 PrepareForPageLoad(navigation_id.main_frame_url, HintOrigin::NAVIGATION);
76 } 88 }
(...skipping 19 matching lines...) Expand all
96 auto it = active_navigations_.find(navigation_id); 108 auto it = active_navigations_.find(navigation_id);
97 if (it != active_navigations_.end()) { 109 if (it != active_navigations_.end()) {
98 const GURL& initial_url = it->second; 110 const GURL& initial_url = it->second;
99 CancelPageLoadHint(initial_url); 111 CancelPageLoadHint(initial_url);
100 active_navigations_.erase(it); 112 active_navigations_.erase(it);
101 } else { 113 } else {
102 CancelPageLoadHint(navigation_id.main_frame_url); 114 CancelPageLoadHint(navigation_id.main_frame_url);
103 } 115 }
104 } 116 }
105 117
118 void LoadingPredictor::SetObserverForTesting(TestLoadingObserver* observer) {
119 observer_ = observer;
120 }
121
106 std::map<GURL, base::TimeTicks>::iterator LoadingPredictor::CancelActiveHint( 122 std::map<GURL, base::TimeTicks>::iterator LoadingPredictor::CancelActiveHint(
107 std::map<GURL, base::TimeTicks>::iterator hint_it) { 123 std::map<GURL, base::TimeTicks>::iterator hint_it) {
108 if (hint_it == active_hints_.end()) 124 if (hint_it == active_hints_.end())
109 return hint_it; 125 return hint_it;
110 126
111 const GURL& url = hint_it->first; 127 const GURL& url = hint_it->first;
112 resource_prefetch_predictor_->StopPrefetching(url); 128 MaybeRemovePrefetch(url);
113 129
114 UMA_HISTOGRAM_TIMES( 130 UMA_HISTOGRAM_TIMES(
115 internal::kResourcePrefetchPredictorPrefetchingDurationHistogram, 131 internal::kResourcePrefetchPredictorPrefetchingDurationHistogram,
116 base::TimeTicks::Now() - hint_it->second); 132 base::TimeTicks::Now() - hint_it->second);
117 return active_hints_.erase(hint_it); 133 return active_hints_.erase(hint_it);
118 } 134 }
119 135
120 void LoadingPredictor::CleanupAbandonedHintsAndNavigations( 136 void LoadingPredictor::CleanupAbandonedHintsAndNavigations(
121 const NavigationID& navigation_id) { 137 const NavigationID& navigation_id) {
122 base::TimeTicks time_now = base::TimeTicks::Now(); 138 base::TimeTicks time_now = base::TimeTicks::Now();
(...skipping 19 matching lines...) Expand all
142 (time_now - it->first.creation_time > max_navigation_age)) { 158 (time_now - it->first.creation_time > max_navigation_age)) {
143 const GURL& initial_url = it->second; 159 const GURL& initial_url = it->second;
144 CancelActiveHint(active_hints_.find(initial_url)); 160 CancelActiveHint(active_hints_.find(initial_url));
145 it = active_navigations_.erase(it); 161 it = active_navigations_.erase(it);
146 } else { 162 } else {
147 ++it; 163 ++it;
148 } 164 }
149 } 165 }
150 } 166 }
151 167
168 void LoadingPredictor::MaybeAddPrefetch(
169 const GURL& url,
170 const ResourcePrefetchPredictor::Prediction& prediction,
171 HintOrigin origin) {
172 if (!config_.IsPrefetchingEnabledForOrigin(profile_, origin))
173 return;
174 std::string host = url.host();
175 if (prefetches_.find(host) != prefetches_.end())
176 return;
177
178 auto prefetcher = base::MakeUnique<ResourcePrefetcher>(
179 GetWeakPtr(), profile_->GetRequestContext(),
180 config_.max_prefetches_inflight_per_navigation,
181 config_.max_prefetches_inflight_per_host_per_navigation, url,
182 prediction.subresource_urls);
183 // base::Unretained(prefetcher.get()) is fine, as |prefetcher| is always
184 // destructed on the IO thread, and the destruction task is posted from the
185 // UI thread, after the current task. Since the IO thread is FIFO, then
186 // ResourcePrefetcher::Start() will be called before ~ResourcePrefetcher.
187 content::BrowserThread::PostTask(
188 content::BrowserThread::IO, FROM_HERE,
189 base::BindOnce(&ResourcePrefetcher::Start,
190 base::Unretained(prefetcher.get())));
191 prefetches_.emplace(host, std::make_pair(std::move(prefetcher), false));
192 if (observer_)
193 observer_->OnPrefetchingStarted(url);
194 }
195
196 void LoadingPredictor::MaybeRemovePrefetch(const GURL& url) {
197 std::string host = url.host();
198 auto it = prefetches_.find(host);
199 if (it == prefetches_.end())
200 return;
201
202 auto& prefetcher_and_deleted = it->second;
203 if (prefetcher_and_deleted.second)
204 return;
205
206 // Avoid to stop the same prefetcher twice, which can happen for instance with
207 // multiple prediction origins for the same |url|. Prefetches are
208 // de-duplicated, not their cancellation.
209 prefetcher_and_deleted.second = true;
210 content::BrowserThread::PostTask(
211 content::BrowserThread::IO, FROM_HERE,
212 base::BindOnce(&ResourcePrefetcher::Stop,
213 base::Unretained(prefetcher_and_deleted.first.get())));
214 if (observer_)
215 observer_->OnPrefetchingStopped(url);
216 }
217
218 void LoadingPredictor::ResourcePrefetcherFinished(
219 ResourcePrefetcher* prefetcher,
220 std::unique_ptr<ResourcePrefetcher::PrefetcherStats> stats) {
221 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
222 std::string host = prefetcher->main_frame_url().host();
223 auto it = prefetches_.find(host);
224 // Can happen after Shutdown() has been called, since it purges |prefetches_|.
225 if (it == prefetches_.end())
226 return;
227
228 DCHECK(it->second.first.get() == prefetcher);
229 stats_collector_->RecordPrefetcherStats(std::move(stats));
230
231 if (observer_)
232 observer_->OnPrefetchingFinished(prefetcher->main_frame_url());
233
234 // ResourcePrefetcher must be destroyed on the IO thread.
235 content::BrowserThread::PostTask(
236 content::BrowserThread::IO, FROM_HERE,
237 base::BindOnce([](std::unique_ptr<ResourcePrefetcher>) {},
238 std::move(it->second.first)));
239
240 prefetches_.erase(it);
241 }
242
243 TestLoadingObserver::~TestLoadingObserver() {
244 predictor_->SetObserverForTesting(nullptr);
245 }
246
247 TestLoadingObserver::TestLoadingObserver(LoadingPredictor* predictor)
248 : predictor_(predictor) {
249 predictor_->SetObserverForTesting(this);
250 }
251
152 } // namespace predictors 252 } // namespace predictors
OLDNEW
« no previous file with comments | « chrome/browser/predictors/loading_predictor.h ('k') | chrome/browser/predictors/resource_prefetch_predictor.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698