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

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

Issue 2928033003: predictors: move ResourcePrefetcher handling to LoadingPredictor. (Closed)
Patch Set: Comments. 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() {
alexilin 2017/07/03 14:55:01 Could LoadingPredictor be destructed without a cal
Benoit L 2017/07/03 15:43:14 No, it can't. Unless we crashed, in which case no
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.
alexilin 2017/07/03 14:55:01 nit: s/prefetchers/|prefetchers|/
Benoit L 2017/07/03 15:43:14 Done.
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);
alexilin 2017/07/03 14:55:01 std::move(prediction.subresource_urls) |prediction
Benoit L 2017/07/03 15:43:14 Thanks! Done.
alexilin 2017/07/03 15:57:14 I'm very suspicious about moving an object (or its
183 content::BrowserThread::PostTask(
184 content::BrowserThread::IO, FROM_HERE,
185 base::BindOnce(&ResourcePrefetcher::Start,
186 base::Unretained(prefetcher.get())));
alexilin 2017/07/03 14:55:01 Can you add a comment explaining that passing unre
Benoit L 2017/07/03 15:43:14 Done.
187 prefetches_.emplace(host, std::make_pair(std::move(prefetcher), false));
188 if (observer_)
189 observer_->OnPrefetchingStarted(url);
190 }
191
192 void LoadingPredictor::MaybeRemovePrefetch(const GURL& url) {
193 std::string host = url.host();
194 auto it = prefetches_.find(host);
195 if (it == prefetches_.end())
196 return;
197
198 auto& prefetcher_and_deleted = it->second;
199 if (prefetcher_and_deleted.second)
200 return;
201
202 // Avoid duplicates.
alexilin 2017/07/03 14:55:01 Can you make this comment more detailed? Something
Benoit L 2017/07/03 15:43:14 Done.
203 prefetcher_and_deleted.second = true;
204 content::BrowserThread::PostTask(
205 content::BrowserThread::IO, FROM_HERE,
206 base::BindOnce(&ResourcePrefetcher::Stop,
207 base::Unretained(prefetcher_and_deleted.first.get())));
208 if (observer_)
209 observer_->OnPrefetchingStopped(url);
210 }
211
212 void LoadingPredictor::ResourcePrefetcherFinished(
213 ResourcePrefetcher* prefetcher,
alexilin 2017/07/03 14:55:01 nit: Do we really need to pass a pointer to Resour
Benoit L 2017/07/03 15:43:14 The lifetime of a ResourcePrefetcher is entirely c
214 std::unique_ptr<ResourcePrefetcher::PrefetcherStats> stats) {
215 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
216 std::string host = prefetcher->main_frame_url().host();
217 auto it = prefetches_.find(host);
218 // Can happen after Shutdown() has been called, since it purges |prefetches_|.
219 if (it == prefetches_.end())
220 return;
221
222 DCHECK(it->second.first.get() == prefetcher);
223 stats_collector_->RecordPrefetcherStats(std::move(stats));
224
225 if (observer_)
226 observer_->OnPrefetchingFinished(prefetcher->main_frame_url());
227
228 // ResourcePrefetcher must be destroyed on the IO thread.
229 content::BrowserThread::PostTask(
230 content::BrowserThread::IO, FROM_HERE,
231 base::BindOnce([](std::unique_ptr<ResourcePrefetcher>) {},
232 base::Passed(std::move(it->second.first))));
alexilin 2017/07/03 14:55:01 Just curious, do you know whether we really need t
Benoit L 2017/07/03 15:43:14 Thanks for letting me know! Done.
233
234 prefetches_.erase(it);
235 }
236
237 TestLoadingObserver::~TestLoadingObserver() {
238 predictor_->SetObserverForTesting(nullptr);
239 }
240
241 TestLoadingObserver::TestLoadingObserver(LoadingPredictor* predictor)
242 : predictor_(predictor) {
243 predictor_->SetObserverForTesting(this);
244 }
245
152 } // namespace predictors 246 } // namespace predictors
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698