OLD | NEW |
1 // Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2010 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/net/url_info.h" | 5 #include "chrome/browser/net/url_info.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <string> | 10 #include <string> |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 kMaxNonNetworkDnsLookupDuration, TimeDelta::FromMinutes(15), 100); | 124 kMaxNonNetworkDnsLookupDuration, TimeDelta::FromMinutes(15), 100); |
125 | 125 |
126 static bool use_ipv6_histogram(FieldTrialList::Find("IPv6_Probe") && | 126 static bool use_ipv6_histogram(FieldTrialList::Find("IPv6_Probe") && |
127 !FieldTrialList::Find("IPv6_Probe")->group_name().empty()); | 127 !FieldTrialList::Find("IPv6_Probe")->group_name().empty()); |
128 if (use_ipv6_histogram) { | 128 if (use_ipv6_histogram) { |
129 UMA_HISTOGRAM_CUSTOM_TIMES( | 129 UMA_HISTOGRAM_CUSTOM_TIMES( |
130 FieldTrial::MakeName("DNS.PrefetchResolution", "IPv6_Probe"), | 130 FieldTrial::MakeName("DNS.PrefetchResolution", "IPv6_Probe"), |
131 resolve_duration_, kMaxNonNetworkDnsLookupDuration, | 131 resolve_duration_, kMaxNonNetworkDnsLookupDuration, |
132 TimeDelta::FromMinutes(15), 100); | 132 TimeDelta::FromMinutes(15), 100); |
133 } | 133 } |
134 | |
135 // Record potential beneficial time, and maybe we'll get a cache hit. | |
136 // We keep the maximum, as the warming we did earlier may still be | |
137 // helping with a cache upstream in DNS resolution. | |
138 benefits_remaining_ = std::max(resolve_duration_, benefits_remaining_); | |
139 } | 134 } |
140 sequence_number_ = sequence_counter++; | 135 sequence_number_ = sequence_counter++; |
141 DLogResultsStats("DNS PrefetchFound"); | 136 DLogResultsStats("DNS PrefetchFound"); |
142 } | 137 } |
143 | 138 |
144 void UrlInfo::SetNoSuchNameState() { | 139 void UrlInfo::SetNoSuchNameState() { |
145 DCHECK(ASSIGNED == state_); | 140 DCHECK(ASSIGNED == state_); |
146 state_ = NO_SUCH_NAME; | 141 state_ = NO_SUCH_NAME; |
147 resolve_duration_ = GetDuration(); | 142 resolve_duration_ = GetDuration(); |
148 if (kMaxNonNetworkDnsLookupDuration <= resolve_duration_) { | 143 if (kMaxNonNetworkDnsLookupDuration <= resolve_duration_) { |
149 DHISTOGRAM_TIMES("DNS.PrefetchNotFoundName", resolve_duration_); | 144 DHISTOGRAM_TIMES("DNS.PrefetchNotFoundName", resolve_duration_); |
150 // Record potential beneficial time, and maybe we'll get a cache hit. | |
151 benefits_remaining_ = std::max(resolve_duration_, benefits_remaining_); | |
152 } | 145 } |
153 sequence_number_ = sequence_counter++; | 146 sequence_number_ = sequence_counter++; |
154 DLogResultsStats("DNS PrefetchNotFound"); | 147 DLogResultsStats("DNS PrefetchNotFound"); |
155 } | 148 } |
156 | 149 |
157 void UrlInfo::SetStartedState() { | |
158 DCHECK(PENDING == state_); | |
159 state_ = STARTED; | |
160 queue_duration_ = resolve_duration_ = TimeDelta(); // 0ms. | |
161 SetMotivation(NO_PREFETCH_MOTIVATION); | |
162 GetDuration(); // Set time. | |
163 } | |
164 | |
165 void UrlInfo::SetFinishedState(bool was_resolved) { | |
166 DCHECK(STARTED == state_); | |
167 state_ = was_resolved ? FINISHED : FINISHED_UNRESOLVED; | |
168 resolve_duration_ = GetDuration(); | |
169 // TODO(jar): Sequence number should be incremented in prefetched HostInfo. | |
170 DLogResultsStats("DNS HTTP Finished"); | |
171 } | |
172 | |
173 void UrlInfo::SetUrl(const GURL& url) { | 150 void UrlInfo::SetUrl(const GURL& url) { |
174 if (url_.is_empty()) // Not yet initialized. | 151 if (url_.is_empty()) // Not yet initialized. |
175 url_ = url; | 152 url_ = url; |
176 else | 153 else |
177 DCHECK_EQ(url_, url); | 154 DCHECK_EQ(url_, url); |
178 } | 155 } |
179 | 156 |
180 // IsStillCached() guesses if the DNS cache still has IP data, | 157 // IsStillCached() guesses if the DNS cache still has IP data, |
181 // or at least remembers results about "not finding host." | 158 // or at least remembers results about "not finding host." |
182 bool UrlInfo::IsStillCached() const { | 159 bool UrlInfo::IsStillCached() const { |
183 DCHECK(FOUND == state_ || NO_SUCH_NAME == state_); | 160 DCHECK(FOUND == state_ || NO_SUCH_NAME == state_); |
184 | 161 |
185 // Default MS OS does not cache failures. Hence we could return false almost | 162 // Default MS OS does not cache failures. Hence we could return false almost |
186 // all the time for that case. However, we'd never try again to prefetch | 163 // all the time for that case. However, we'd never try again to prefetch |
187 // the value if we returned false that way. Hence we'll just let the lookup | 164 // the value if we returned false that way. Hence we'll just let the lookup |
188 // time out the same way as FOUND case. | 165 // time out the same way as FOUND case. |
189 | 166 |
190 if (sequence_counter - sequence_number_ > kMaxGuaranteedDnsCacheSize) | 167 if (sequence_counter - sequence_number_ > kMaxGuaranteedDnsCacheSize) |
191 return false; | 168 return false; |
192 | 169 |
193 TimeDelta time_since_resolution = TimeTicks::Now() - time_; | 170 TimeDelta time_since_resolution = TimeTicks::Now() - time_; |
194 | 171 |
195 return time_since_resolution < kCacheExpirationDuration; | 172 return time_since_resolution < kCacheExpirationDuration; |
196 } | 173 } |
197 | 174 |
198 // Compare the actual navigation DNS latency found in navigation_info, to the | |
199 // previously prefetched info. | |
200 DnsBenefit UrlInfo::AccruePrefetchBenefits(UrlInfo* navigation_info) { | |
201 DCHECK(FINISHED == navigation_info->state_ || | |
202 FINISHED_UNRESOLVED == navigation_info->state_); | |
203 DCHECK(navigation_info->url() == url_); | |
204 | |
205 if ((0 == benefits_remaining_.InMilliseconds()) || | |
206 (FOUND != state_ && NO_SUCH_NAME != state_)) { | |
207 if (FINISHED == navigation_info->state_) | |
208 UMA_HISTOGRAM_LONG_TIMES("DNS.IndependentNavigation", | |
209 navigation_info->resolve_duration_); | |
210 else | |
211 UMA_HISTOGRAM_LONG_TIMES("DNS.IndependentFailedNavigation", | |
212 navigation_info->resolve_duration_); | |
213 return PREFETCH_NO_BENEFIT; | |
214 } | |
215 | |
216 TimeDelta benefit = benefits_remaining_ - navigation_info->resolve_duration_; | |
217 navigation_info->benefits_remaining_ = benefits_remaining_; | |
218 benefits_remaining_ = TimeDelta(); // We used up all our benefits here. | |
219 | |
220 navigation_info->motivation_ = motivation_; | |
221 if (LEARNED_REFERAL_MOTIVATED == motivation_ || | |
222 STATIC_REFERAL_MOTIVATED == motivation_) | |
223 navigation_info->referring_url_ = referring_url_; | |
224 | |
225 if (navigation_info->resolve_duration_ > kMaxNonNetworkDnsLookupDuration) { | |
226 // Our precache effort didn't help since HTTP stack hit the network. | |
227 UMA_HISTOGRAM_LONG_TIMES("DNS.PrefetchCacheEvictionL", resolve_duration_); | |
228 DLogResultsStats("DNS PrefetchCacheEviction"); | |
229 return PREFETCH_CACHE_EVICTION; | |
230 } | |
231 | |
232 if (NO_SUCH_NAME == state_) { | |
233 UMA_HISTOGRAM_LONG_TIMES("DNS.PrefetchNegativeHitL", benefit); | |
234 DLogResultsStats("DNS PrefetchNegativeHit"); | |
235 return PREFETCH_NAME_NONEXISTANT; | |
236 } | |
237 | |
238 DCHECK_EQ(FOUND, state_); | |
239 if (LEARNED_REFERAL_MOTIVATED == motivation_ || | |
240 STATIC_REFERAL_MOTIVATED == motivation_) { | |
241 UMA_HISTOGRAM_TIMES("DNS.PrefetchReferredPositiveHit", benefit); | |
242 DLogResultsStats("DNS PrefetchReferredPositiveHit"); | |
243 } else { | |
244 UMA_HISTOGRAM_LONG_TIMES("DNS.PrefetchPositiveHitL", benefit); | |
245 DLogResultsStats("DNS PrefetchPositiveHit"); | |
246 } | |
247 return PREFETCH_NAME_FOUND; | |
248 } | |
249 | |
250 void UrlInfo::DLogResultsStats(const char* message) const { | 175 void UrlInfo::DLogResultsStats(const char* message) const { |
251 if (!detailed_logging_enabled) | 176 if (!detailed_logging_enabled) |
252 return; | 177 return; |
253 DLOG(INFO) << "\t" << message << "\tq=" | 178 DLOG(INFO) << "\t" << message << "\tq=" |
254 << queue_duration().InMilliseconds() << "ms,\tr=" | 179 << queue_duration().InMilliseconds() << "ms,\tr=" |
255 << resolve_duration().InMilliseconds() << "ms\tp=" | 180 << resolve_duration().InMilliseconds() << "ms\tp=" |
256 << benefits_remaining_.InMilliseconds() << "ms\tseq=" | |
257 << sequence_number_ | 181 << sequence_number_ |
258 << "\t" << url_.spec(); | 182 << "\t" << url_.spec(); |
259 } | 183 } |
260 | 184 |
261 //------------------------------------------------------------------------------ | 185 //------------------------------------------------------------------------------ |
262 // This last section supports HTML output, such as seen in about:dns. | 186 // This last section supports HTML output, such as seen in about:dns. |
263 //------------------------------------------------------------------------------ | 187 //------------------------------------------------------------------------------ |
264 | 188 |
265 // Preclude any possibility of Java Script or markup in the text, by only | 189 // Preclude any possibility of Java Script or markup in the text, by only |
266 // allowing alphanumerics, '.', '-', ':', and whitespace. | 190 // allowing alphanumerics, '.', '-', ':', and whitespace. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
322 int print_hours = minutes/60; | 246 int print_hours = minutes/60; |
323 if (print_hours) | 247 if (print_hours) |
324 StringAppendF(&result, "%.2d:", print_hours); | 248 StringAppendF(&result, "%.2d:", print_hours); |
325 if (print_hours || print_minutes) | 249 if (print_hours || print_minutes) |
326 StringAppendF(&result, "%2.2d:", print_minutes); | 250 StringAppendF(&result, "%2.2d:", print_minutes); |
327 StringAppendF(&result, "%2.2d", print_seconds); | 251 StringAppendF(&result, "%2.2d", print_seconds); |
328 return result; | 252 return result; |
329 } | 253 } |
330 | 254 |
331 // static | 255 // static |
332 void UrlInfo::GetHtmlTable(const DnsInfoTable host_infos, | 256 void UrlInfo::GetHtmlTable(const UrlInfoTable host_infos, |
333 const char* description, | 257 const char* description, |
334 const bool brief, | 258 const bool brief, |
335 std::string* output) { | 259 std::string* output) { |
336 if (0 == host_infos.size()) | 260 if (0 == host_infos.size()) |
337 return; | 261 return; |
338 output->append(description); | 262 output->append(description); |
339 StringAppendF(output, "%" PRIuS " %s", host_infos.size(), | 263 StringAppendF(output, "%" PRIuS " %s", host_infos.size(), |
340 (1 == host_infos.size()) ? "hostname" : "hostnames"); | 264 (1 == host_infos.size()) ? "hostname" : "hostnames"); |
341 | 265 |
342 if (brief) { | 266 if (brief) { |
343 output->append("<br><br>"); | 267 output->append("<br><br>"); |
344 return; | 268 return; |
345 } | 269 } |
346 | 270 |
347 const char* row_format = "<tr align=right><td>%s</td>" | 271 output->append("<br><table border=1>" |
348 "<td>%d</td><td>%d</td><td>%s</td><td>%s</td></tr>"; | 272 "<tr><th>Host name</th>" |
| 273 "<th>How long ago<br>(HH:MM:SS)</th>" |
| 274 "<th>Motivation</th>" |
| 275 "</tr>"); |
349 | 276 |
350 output->append("<br><table border=1>"); | 277 const char* row_format = "<tr align=right><td>%s</td>" // Host name. |
351 StringAppendF(output, | 278 "<td>%s</td>" // How long ago. |
352 "<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr>", | 279 "<td>%s</td>" // Motivation. |
353 "Host name", "Applicable Prefetch<br>Time (ms)", | 280 "</tr>"; |
354 "Recent Resolution<br>Time(ms)", "How long ago<br>(HH:MM:SS)", | |
355 "Motivation"); | |
356 | 281 |
357 // Print bulk of table, and gather stats at same time. | 282 // Print bulk of table, and gather stats at same time. |
358 MinMaxAverage queue, resolve, preresolve, when; | 283 MinMaxAverage queue, when; |
359 TimeTicks current_time = TimeTicks::Now(); | 284 TimeTicks current_time = TimeTicks::Now(); |
360 for (DnsInfoTable::const_iterator it(host_infos.begin()); | 285 for (UrlInfoTable::const_iterator it(host_infos.begin()); |
361 it != host_infos.end(); it++) { | 286 it != host_infos.end(); it++) { |
362 queue.sample((it->queue_duration_.InMilliseconds())); | 287 queue.sample((it->queue_duration_.InMilliseconds())); |
363 StringAppendF(output, row_format, | 288 StringAppendF(output, row_format, |
364 RemoveJs(it->url_.spec()).c_str(), | 289 RemoveJs(it->url_.spec()).c_str(), |
365 preresolve.sample((it->benefits_remaining_.InMilliseconds())), | |
366 resolve.sample((it->resolve_duration_.InMilliseconds())), | |
367 HoursMinutesSeconds(when.sample( | 290 HoursMinutesSeconds(when.sample( |
368 (current_time - it->time_).InSeconds())).c_str(), | 291 (current_time - it->time_).InSeconds())).c_str(), |
369 it->GetAsciiMotivation().c_str()); | 292 it->GetAsciiMotivation().c_str()); |
370 } | 293 } |
371 // Write min, max, and average summary lines. | |
372 if (host_infos.size() > 2) { | |
373 output->append("<B>"); | |
374 StringAppendF(output, row_format, | |
375 "<b>---minimum---</b>", | |
376 preresolve.minimum(), resolve.minimum(), | |
377 HoursMinutesSeconds(when.minimum()).c_str(), ""); | |
378 StringAppendF(output, row_format, | |
379 "<b>---average---</b>", | |
380 preresolve.average(), resolve.average(), | |
381 HoursMinutesSeconds(when.average()).c_str(), ""); | |
382 StringAppendF(output, row_format, | |
383 "<b>standard deviation</b>", | |
384 preresolve.standard_deviation(), | |
385 resolve.standard_deviation(), "n/a", ""); | |
386 StringAppendF(output, row_format, | |
387 "<b>---maximum---</b>", | |
388 preresolve.maximum(), resolve.maximum(), | |
389 HoursMinutesSeconds(when.maximum()).c_str(), ""); | |
390 StringAppendF(output, row_format, | |
391 "<b>-----SUM-----</b>", | |
392 preresolve.sum(), resolve.sum(), "n/a", ""); | |
393 } | |
394 output->append("</table>"); | 294 output->append("</table>"); |
395 | 295 |
396 #ifdef DEBUG | 296 #ifdef DEBUG |
397 StringAppendF(output, | 297 StringAppendF(output, |
398 "Prefetch Queue Durations: min=%d, avg=%d, max=%d<br><br>", | 298 "Prefetch Queue Durations: min=%d, avg=%d, max=%d<br><br>", |
399 queue.minimum(), queue.average(), queue.maximum()); | 299 queue.minimum(), queue.average(), queue.maximum()); |
400 #endif | 300 #endif |
401 | 301 |
402 output->append("<br>"); | 302 output->append("<br>"); |
403 } | 303 } |
(...skipping 26 matching lines...) Expand all Loading... |
430 | 330 |
431 case LEARNED_REFERAL_MOTIVATED: | 331 case LEARNED_REFERAL_MOTIVATED: |
432 return RemoveJs(referring_url_.spec()); | 332 return RemoveJs(referring_url_.spec()); |
433 | 333 |
434 default: | 334 default: |
435 return ""; | 335 return ""; |
436 } | 336 } |
437 } | 337 } |
438 | 338 |
439 } // namespace chrome_browser_net | 339 } // namespace chrome_browser_net |
OLD | NEW |