Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/resource_prefetch_predictor.h" | 5 #include "chrome/browser/predictors/resource_prefetch_predictor.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <set> | 8 #include <set> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 13 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
| 14 #include "base/string_number_conversions.h" | |
| 15 #include "base/stringprintf.h" | |
| 14 #include "base/time.h" | 16 #include "base/time.h" |
| 15 #include "chrome/browser/history/history.h" | 17 #include "chrome/browser/history/history.h" |
| 16 #include "chrome/browser/history/history_notifications.h" | 18 #include "chrome/browser/history/history_notifications.h" |
| 17 #include "chrome/browser/history/history_service_factory.h" | 19 #include "chrome/browser/history/history_service_factory.h" |
| 18 #include "chrome/browser/history/in_memory_database.h" | 20 #include "chrome/browser/history/in_memory_database.h" |
| 19 #include "chrome/browser/history/url_database.h" | 21 #include "chrome/browser/history/url_database.h" |
| 20 #include "chrome/browser/predictors/predictor_database.h" | 22 #include "chrome/browser/predictors/predictor_database.h" |
| 21 #include "chrome/browser/predictors/predictor_database_factory.h" | 23 #include "chrome/browser/predictors/predictor_database_factory.h" |
| 22 #include "chrome/browser/prerender/prerender_field_trial.h" | 24 #include "chrome/browser/prerender/prerender_field_trial.h" |
| 23 #include "chrome/browser/profiles/profile.h" | 25 #include "chrome/browser/profiles/profile.h" |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 37 #include "net/url_request/url_request.h" | 39 #include "net/url_request/url_request.h" |
| 38 #include "net/url_request/url_request_context_getter.h" | 40 #include "net/url_request/url_request_context_getter.h" |
| 39 | 41 |
| 40 using content::BrowserThread; | 42 using content::BrowserThread; |
| 41 | 43 |
| 42 namespace { | 44 namespace { |
| 43 | 45 |
| 44 // Don't store subresources whose Urls are longer than this. | 46 // Don't store subresources whose Urls are longer than this. |
| 45 size_t kMaxSubresourceUrlLengthBytes = 1000; | 47 size_t kMaxSubresourceUrlLengthBytes = 1000; |
| 46 | 48 |
| 47 // For reporting histograms about navigation status. | |
| 48 enum NavigationStatus { | |
| 49 NAVIGATION_STATUS_COMPLETE = 0, | |
| 50 NAVIGATION_STATUS_COMPLETE_ABANDONED = 1, | |
| 51 NAVIGATION_STATUS_ABANDONED = 2, | |
| 52 NAVIGATION_STATUS_COUNT = 3 | |
| 53 }; | |
| 54 | |
| 55 // For reporting whether a subresource is handled or not, and for what reasons. | 49 // For reporting whether a subresource is handled or not, and for what reasons. |
| 56 enum ResourceStatus { | 50 enum ResourceStatus { |
| 57 RESOURCE_STATUS_HANDLED = 0, | 51 RESOURCE_STATUS_HANDLED = 0, |
| 58 RESOURCE_STATUS_NOT_HTTP_PAGE = 1, | 52 RESOURCE_STATUS_NOT_HTTP_PAGE = 1, |
| 59 RESOURCE_STATUS_NOT_HTTP_RESOURCE = 2, | 53 RESOURCE_STATUS_NOT_HTTP_RESOURCE = 2, |
| 60 RESOURCE_STATUS_UNSUPPORTED_MIME_TYPE = 4, | 54 RESOURCE_STATUS_UNSUPPORTED_MIME_TYPE = 4, |
| 61 RESOURCE_STATUS_NOT_GET = 8, | 55 RESOURCE_STATUS_NOT_GET = 8, |
| 62 RESOURCE_STATUS_URL_TOO_LONG = 16, | 56 RESOURCE_STATUS_URL_TOO_LONG = 16, |
| 63 RESOURCE_STATUS_NOT_CACHEABLE = 32, | 57 RESOURCE_STATUS_NOT_CACHEABLE = 32, |
| 64 RESOURCE_STATUS_HEADERS_MISSING = 64, | 58 RESOURCE_STATUS_HEADERS_MISSING = 64, |
| 65 RESOURCE_STATUS_MAX = 128, | 59 RESOURCE_STATUS_MAX = 128, |
| 66 }; | 60 }; |
| 67 | 61 |
| 62 // For reporting various interesting events that occur during the loading of a | |
| 63 // single main frame. | |
| 64 enum NavigationEvent { | |
| 65 NAVIGATION_EVENT_REQUEST_STARTED = 0, | |
| 66 NAVIGATION_EVENT_REQUEST_REDIRECTED = 1, | |
| 67 NAVIGATION_EVENT_REQUEST_REDIRECTED_EMPTY_URL = 2, | |
| 68 NAVIGATION_EVENT_REQUEST_EXPIRED = 3, | |
| 69 NAVIGATION_EVENT_RESPONSE_STARTED = 4, | |
| 70 NAVIGATION_EVENT_ONLOAD = 5, | |
| 71 NAVIGATION_EVENT_ONLOAD_EMPTY_URL = 6, | |
| 72 NAVIGATION_EVENT_ONLOAD_UNTRACKED_URL = 7, | |
| 73 NAVIGATION_EVENT_ONLOAD_TRACKED_URL = 8, | |
| 74 NAVIGATION_EVENT_SHOULD_TRACK_URL = 9, | |
| 75 NAVIGATION_EVENT_SHOULD_NOT_TRACK_URL = 10, | |
| 76 NAVIGATION_EVENT_URL_TABLE_FULL = 11, | |
| 77 NAVIGATION_EVENT_HAVE_PREDICTIONS_FOR_URL = 12, | |
| 78 NAVIGATION_EVENT_NO_PREDICTIONS_FOR_URL = 13, | |
| 79 NAVIGATION_EVENT_COUNT = 14, | |
| 80 }; | |
| 81 | |
| 68 } // namespace | 82 } // namespace |
| 69 | 83 |
| 70 namespace predictors { | 84 namespace predictors { |
| 71 | 85 |
| 72 ResourcePrefetchPredictor::Config::Config() | 86 ResourcePrefetchPredictor::Config::Config() |
| 73 : max_navigation_lifetime_seconds(60), | 87 : max_navigation_lifetime_seconds(60), |
| 74 max_urls_to_track(500), | 88 max_urls_to_track(500), |
| 75 min_url_visit_count(3), | 89 min_url_visit_count(3), |
| 76 max_resources_per_entry(50), | 90 max_resources_per_entry(50), |
| 77 max_consecutive_misses(3), | 91 max_consecutive_misses(3) { |
| 78 num_resources_assumed_prefetched(25) { | |
| 79 } | 92 } |
| 80 | 93 |
| 81 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary() | 94 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary() |
| 82 : resource_type(ResourceType::LAST_TYPE), | 95 : resource_type(ResourceType::LAST_TYPE), |
| 83 was_cached(false) { | 96 was_cached(false) { |
| 84 } | 97 } |
| 85 | 98 |
| 86 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary( | 99 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary( |
| 87 const URLRequestSummary& other) | 100 const URLRequestSummary& other) |
| 88 : navigation_id(other.navigation_id), | 101 : navigation_id(other.navigation_id), |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 151 DCHECK_EQ(initialization_state_, INITIALIZING); | 164 DCHECK_EQ(initialization_state_, INITIALIZING); |
| 152 DCHECK(url_table_cache_.empty()); | 165 DCHECK(url_table_cache_.empty()); |
| 153 DCHECK(inflight_navigations_.empty()); | 166 DCHECK(inflight_navigations_.empty()); |
| 154 | 167 |
| 155 // Copy the data to local caches. | 168 // Copy the data to local caches. |
| 156 for (UrlTableRowVector::iterator it = url_rows->begin(); | 169 for (UrlTableRowVector::iterator it = url_rows->begin(); |
| 157 it != url_rows->end(); ++it) { | 170 it != url_rows->end(); ++it) { |
| 158 url_table_cache_[it->main_frame_url].rows.push_back(*it); | 171 url_table_cache_[it->main_frame_url].rows.push_back(*it); |
| 159 } | 172 } |
| 160 | 173 |
| 174 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.UrlTableMainFrameUrlCount", | |
| 175 url_table_cache_.size()); | |
| 176 | |
| 161 // Score and sort the database caches. | 177 // Score and sort the database caches. |
| 162 // TODO(shishir): The following would be much more efficient if we used | 178 // TODO(shishir): The following would be much more efficient if we used |
| 163 // pointers. | 179 // pointers. |
| 164 for (UrlTableCacheMap::iterator it = url_table_cache_.begin(); | 180 for (UrlTableCacheMap::iterator it = url_table_cache_.begin(); |
| 165 it != url_table_cache_.end(); ++it) { | 181 it != url_table_cache_.end(); ++it) { |
| 166 std::sort(it->second.rows.begin(), | 182 std::sort(it->second.rows.begin(), |
| 167 it->second.rows.end(), | 183 it->second.rows.end(), |
| 168 ResourcePrefetchPredictorTables::UrlTableRowSorter()); | 184 ResourcePrefetchPredictorTables::UrlTableRowSorter()); |
| 169 } | 185 } |
| 170 | 186 |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 323 | 339 |
| 324 CHECK_EQ(response.resource_type, ResourceType::MAIN_FRAME); | 340 CHECK_EQ(response.resource_type, ResourceType::MAIN_FRAME); |
| 325 OnMainFrameRedirect(response); | 341 OnMainFrameRedirect(response); |
| 326 } | 342 } |
| 327 | 343 |
| 328 void ResourcePrefetchPredictor::OnMainFrameRequest( | 344 void ResourcePrefetchPredictor::OnMainFrameRequest( |
| 329 const URLRequestSummary& request) { | 345 const URLRequestSummary& request) { |
| 330 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 346 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 331 DCHECK_EQ(INITIALIZED, initialization_state_); | 347 DCHECK_EQ(INITIALIZED, initialization_state_); |
| 332 | 348 |
| 349 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationEvent", | |
| 350 NAVIGATION_EVENT_REQUEST_STARTED, | |
| 351 NAVIGATION_EVENT_COUNT); | |
| 352 | |
| 333 // Cleanup older navigations. | 353 // Cleanup older navigations. |
| 334 CleanupAbandonedNavigations(request.navigation_id); | 354 CleanupAbandonedNavigations(request.navigation_id); |
| 335 | 355 |
| 336 // New empty navigation entry. | 356 // New empty navigation entry. |
| 337 inflight_navigations_.insert(std::make_pair( | 357 inflight_navigations_.insert(std::make_pair( |
| 338 request.navigation_id, std::vector<URLRequestSummary>())); | 358 request.navigation_id, std::vector<URLRequestSummary>())); |
| 339 } | 359 } |
| 340 | 360 |
| 341 void ResourcePrefetchPredictor::OnMainFrameResponse( | 361 void ResourcePrefetchPredictor::OnMainFrameResponse( |
| 342 const URLRequestSummary& response) { | 362 const URLRequestSummary& response) { |
| 343 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 363 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 344 | 364 |
| 365 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationEvent", | |
| 366 NAVIGATION_EVENT_RESPONSE_STARTED, | |
| 367 NAVIGATION_EVENT_COUNT); | |
| 368 | |
| 345 // TODO(shishir): The prefreshing will be stopped here. | 369 // TODO(shishir): The prefreshing will be stopped here. |
| 346 } | 370 } |
| 347 | 371 |
| 348 void ResourcePrefetchPredictor::OnMainFrameRedirect( | 372 void ResourcePrefetchPredictor::OnMainFrameRedirect( |
| 349 const URLRequestSummary& response) { | 373 const URLRequestSummary& response) { |
| 350 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 374 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 351 | 375 |
| 376 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationEvent", | |
| 377 NAVIGATION_EVENT_REQUEST_REDIRECTED, | |
| 378 NAVIGATION_EVENT_COUNT); | |
| 379 | |
| 352 // Remove the older navigation. | 380 // Remove the older navigation. |
| 353 inflight_navigations_.erase(response.navigation_id); | 381 inflight_navigations_.erase(response.navigation_id); |
| 354 | 382 |
| 355 // A redirect will not lead to another OnMainFrameRequest call, so record the | 383 // A redirect will not lead to another OnMainFrameRequest call, so record the |
| 356 // redirect url as a new navigation. | 384 // redirect url as a new navigation. |
| 357 | 385 |
| 358 // The redirect url may be empty if the url was invalid. | 386 // The redirect url may be empty if the url was invalid. |
| 359 if (response.redirect_url.is_empty()) | 387 if (response.redirect_url.is_empty()) { |
| 388 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationEvent", | |
| 389 NAVIGATION_EVENT_REQUEST_REDIRECTED_EMPTY_URL, | |
| 390 NAVIGATION_EVENT_COUNT); | |
| 360 return; | 391 return; |
| 392 } | |
| 361 | 393 |
| 362 NavigationID navigation_id(response.navigation_id); | 394 NavigationID navigation_id(response.navigation_id); |
| 363 navigation_id.main_frame_url = response.redirect_url; | 395 navigation_id.main_frame_url = response.redirect_url; |
| 364 inflight_navigations_.insert(std::make_pair( | 396 inflight_navigations_.insert(std::make_pair( |
| 365 navigation_id, std::vector<URLRequestSummary>())); | 397 navigation_id, std::vector<URLRequestSummary>())); |
| 366 } | 398 } |
| 367 | 399 |
| 368 void ResourcePrefetchPredictor::OnSubresourceResponse( | 400 void ResourcePrefetchPredictor::OnSubresourceResponse( |
| 369 const URLRequestSummary& response) { | 401 const URLRequestSummary& response) { |
| 370 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 402 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 398 const NavigationID& navigation_id) { | 430 const NavigationID& navigation_id) { |
| 399 static const base::TimeDelta max_navigation_age = | 431 static const base::TimeDelta max_navigation_age = |
| 400 base::TimeDelta::FromSeconds(config_.max_navigation_lifetime_seconds); | 432 base::TimeDelta::FromSeconds(config_.max_navigation_lifetime_seconds); |
| 401 | 433 |
| 402 base::TimeTicks time_now = base::TimeTicks::Now(); | 434 base::TimeTicks time_now = base::TimeTicks::Now(); |
| 403 for (NavigationMap::iterator it = inflight_navigations_.begin(); | 435 for (NavigationMap::iterator it = inflight_navigations_.begin(); |
| 404 it != inflight_navigations_.end();) { | 436 it != inflight_navigations_.end();) { |
| 405 if (it->first.IsSameRenderer(navigation_id) || | 437 if (it->first.IsSameRenderer(navigation_id) || |
| 406 (time_now - it->first.creation_time > max_navigation_age)) { | 438 (time_now - it->first.creation_time > max_navigation_age)) { |
| 407 inflight_navigations_.erase(it++); | 439 inflight_navigations_.erase(it++); |
| 408 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationStatus", | 440 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationEvent", |
| 409 NAVIGATION_STATUS_ABANDONED, | 441 NAVIGATION_EVENT_REQUEST_EXPIRED, |
| 410 NAVIGATION_STATUS_COUNT); | 442 NAVIGATION_EVENT_COUNT); |
| 411 } else { | 443 } else { |
| 412 ++it; | 444 ++it; |
| 413 } | 445 } |
| 414 } | 446 } |
| 415 } | 447 } |
| 416 | 448 |
| 417 void ResourcePrefetchPredictor::Observe( | 449 void ResourcePrefetchPredictor::Observe( |
| 418 int type, | 450 int type, |
| 419 const content::NotificationSource& source, | 451 const content::NotificationSource& source, |
| 420 const content::NotificationDetails& details) { | 452 const content::NotificationDetails& details) { |
| 421 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 453 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 422 | 454 |
| 423 switch (type) { | 455 switch (type) { |
| 424 case content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME: { | 456 case content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME: { |
| 457 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationEvent", | |
| 458 NAVIGATION_EVENT_ONLOAD, | |
| 459 NAVIGATION_EVENT_COUNT); | |
| 425 const content::WebContents* web_contents = | 460 const content::WebContents* web_contents = |
| 426 content::Source<content::WebContents>(source).ptr(); | 461 content::Source<content::WebContents>(source).ptr(); |
| 427 NavigationID navigation_id(*web_contents); | 462 NavigationID navigation_id(*web_contents); |
| 428 // WebContents can return an empty URL if the navigation entry | 463 // WebContents can return an empty URL if the navigation entry |
| 429 // corresponding to the navigation has not been created yet. | 464 // corresponding to the navigation has not been created yet. |
| 430 if (!navigation_id.main_frame_url.is_empty()) | 465 if (navigation_id.main_frame_url.is_empty()) { |
| 466 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationEvent", | |
| 467 NAVIGATION_EVENT_ONLOAD_EMPTY_URL, | |
| 468 NAVIGATION_EVENT_COUNT); | |
| 469 | |
| 470 } else { | |
| 431 OnNavigationComplete(navigation_id); | 471 OnNavigationComplete(navigation_id); |
| 472 } | |
| 432 break; | 473 break; |
| 433 } | 474 } |
| 434 | 475 |
| 435 case content::NOTIFICATION_LOAD_FROM_MEMORY_CACHE: { | 476 case content::NOTIFICATION_LOAD_FROM_MEMORY_CACHE: { |
| 436 const content::LoadFromMemoryCacheDetails* load_details = | 477 const content::LoadFromMemoryCacheDetails* load_details = |
| 437 content::Details<content::LoadFromMemoryCacheDetails>(details).ptr(); | 478 content::Details<content::LoadFromMemoryCacheDetails>(details).ptr(); |
| 438 const content::WebContents* web_contents = | 479 const content::WebContents* web_contents = |
| 439 content::Source<content::NavigationController>( | 480 content::Source<content::NavigationController>( |
| 440 source).ptr()->GetWebContents(); | 481 source).ptr()->GetWebContents(); |
| 441 | 482 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 489 it != url_table_cache_.end();) { | 530 it != url_table_cache_.end();) { |
| 490 history::URLRow url_row; | 531 history::URLRow url_row; |
| 491 if (url_db->GetRowForURL(it->first, &url_row) == 0) { | 532 if (url_db->GetRowForURL(it->first, &url_row) == 0) { |
| 492 urls_to_delete.push_back(it->first); | 533 urls_to_delete.push_back(it->first); |
| 493 url_table_cache_.erase(it++); | 534 url_table_cache_.erase(it++); |
| 494 } else { | 535 } else { |
| 495 it->second.last_visit = url_row.last_visit(); | 536 it->second.last_visit = url_row.last_visit(); |
| 496 ++it; | 537 ++it; |
| 497 } | 538 } |
| 498 } | 539 } |
| 499 if (!urls_to_delete.empty()) | 540 |
| 541 if (!urls_to_delete.empty()) { | |
| 542 UMA_HISTOGRAM_COUNTS( | |
| 543 "ResourcePrefetchPredictor.UrlTableMainFrameUrlsDeletedNotInHistory", | |
| 544 urls_to_delete.size()); | |
| 545 UMA_HISTOGRAM_PERCENTAGE( | |
| 546 "ResourcePrefetchPredictor." | |
| 547 "UrlTableMainFrameUrlsDeletedNotInHistoryPercent", | |
| 548 urls_to_delete.size() * 100.0 / url_table_cache_.size()); | |
| 549 | |
| 500 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 550 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, |
| 501 base::Bind(&ResourcePrefetchPredictorTables::DeleteRowsForUrls, | 551 base::Bind(&ResourcePrefetchPredictorTables::DeleteRowsForUrls, |
| 502 tables_, | 552 tables_, |
| 503 urls_to_delete)); | 553 urls_to_delete)); |
| 554 } | |
| 504 } | 555 } |
| 505 | 556 |
| 506 notification_registrar_.Add(this, | 557 notification_registrar_.Add(this, |
| 507 content::NOTIFICATION_LOAD_FROM_MEMORY_CACHE, | 558 content::NOTIFICATION_LOAD_FROM_MEMORY_CACHE, |
| 508 content::NotificationService::AllSources()); | 559 content::NotificationService::AllSources()); |
| 509 notification_registrar_.Add(this, | 560 notification_registrar_.Add(this, |
| 510 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, | 561 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, |
| 511 content::NotificationService::AllSources()); | 562 content::NotificationService::AllSources()); |
| 512 notification_registrar_.Add(this, | 563 notification_registrar_.Add(this, |
| 513 chrome::NOTIFICATION_HISTORY_URLS_DELETED, | 564 chrome::NOTIFICATION_HISTORY_URLS_DELETED, |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 524 return true; | 575 return true; |
| 525 | 576 |
| 526 HistoryService* history_service = HistoryServiceFactory::GetForProfile( | 577 HistoryService* history_service = HistoryServiceFactory::GetForProfile( |
| 527 profile_, Profile::EXPLICIT_ACCESS); | 578 profile_, Profile::EXPLICIT_ACCESS); |
| 528 DCHECK(history_service); | 579 DCHECK(history_service); |
| 529 history::URLDatabase* url_db = history_service->InMemoryDatabase(); | 580 history::URLDatabase* url_db = history_service->InMemoryDatabase(); |
| 530 if (!url_db) | 581 if (!url_db) |
| 531 return false; | 582 return false; |
| 532 | 583 |
| 533 history::URLRow url_row; | 584 history::URLRow url_row; |
| 534 return url_db->GetRowForURL(url, &url_row) != 0 && | 585 int visit_count = 0; |
| 535 url_row.visit_count() >= config_.min_url_visit_count; | 586 if (url_db->GetRowForURL(url, &url_row) != 0) |
| 587 visit_count = url_row.visit_count(); | |
| 588 | |
| 589 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HistoryVisitCountForUrl", | |
| 590 visit_count); | |
| 591 | |
| 592 return visit_count >= config_.min_url_visit_count; | |
| 536 } | 593 } |
| 537 | 594 |
| 538 void ResourcePrefetchPredictor::OnNavigationComplete( | 595 void ResourcePrefetchPredictor::OnNavigationComplete( |
| 539 const NavigationID& navigation_id) { | 596 const NavigationID& navigation_id) { |
| 540 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 597 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 541 | 598 |
| 542 if (inflight_navigations_.find(navigation_id) == | 599 if (inflight_navigations_.find(navigation_id) == |
| 543 inflight_navigations_.end()) { | 600 inflight_navigations_.end()) { |
| 544 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationStatus", | 601 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationEvent", |
| 545 NAVIGATION_STATUS_COMPLETE_ABANDONED, | 602 NAVIGATION_EVENT_ONLOAD_UNTRACKED_URL, |
| 546 NAVIGATION_STATUS_COUNT); | 603 NAVIGATION_EVENT_COUNT); |
| 547 return; | 604 return; |
| 548 } | 605 } |
| 549 | 606 |
| 550 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationStatus", | 607 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationEvent", |
| 551 NAVIGATION_STATUS_COMPLETE, | 608 NAVIGATION_EVENT_ONLOAD_TRACKED_URL, |
| 552 NAVIGATION_STATUS_COUNT); | 609 NAVIGATION_EVENT_COUNT); |
| 553 | 610 |
| 554 // Report any stats. | 611 // Report any stats. |
| 555 MaybeReportAccuracyStats(navigation_id); | 612 MaybeReportAccuracyStats(navigation_id); |
| 556 | 613 |
| 557 // Update the URL table. | 614 // Update the URL table. |
| 558 const GURL& main_frame_url = navigation_id.main_frame_url; | 615 const GURL& main_frame_url = navigation_id.main_frame_url; |
| 559 if (ShouldTrackUrl(main_frame_url)) | 616 if (ShouldTrackUrl(main_frame_url)) { |
| 617 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationEvent", | |
| 618 NAVIGATION_EVENT_SHOULD_TRACK_URL, | |
| 619 NAVIGATION_EVENT_COUNT); | |
| 560 LearnUrlNavigation(main_frame_url, inflight_navigations_[navigation_id]); | 620 LearnUrlNavigation(main_frame_url, inflight_navigations_[navigation_id]); |
| 621 } else { | |
| 622 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationEvent", | |
| 623 NAVIGATION_EVENT_SHOULD_NOT_TRACK_URL, | |
| 624 NAVIGATION_EVENT_COUNT); | |
| 625 } | |
| 561 | 626 |
| 562 // Remove the navigation. | 627 // Remove the navigation. |
| 563 inflight_navigations_.erase(navigation_id); | 628 inflight_navigations_.erase(navigation_id); |
| 564 } | 629 } |
| 565 | 630 |
| 566 void ResourcePrefetchPredictor::LearnUrlNavigation( | 631 void ResourcePrefetchPredictor::LearnUrlNavigation( |
| 567 const GURL& main_frame_url, | 632 const GURL& main_frame_url, |
| 568 const std::vector<URLRequestSummary>& new_resources) { | 633 const std::vector<URLRequestSummary>& new_resources) { |
| 569 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 634 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 570 | 635 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 671 base::Bind(&ResourcePrefetchPredictorTables::UpdateRowsForUrl, | 736 base::Bind(&ResourcePrefetchPredictorTables::UpdateRowsForUrl, |
| 672 tables_, | 737 tables_, |
| 673 main_frame_url, | 738 main_frame_url, |
| 674 rows)); | 739 rows)); |
| 675 } | 740 } |
| 676 | 741 |
| 677 void ResourcePrefetchPredictor::RemoveAnEntryFromUrlDB() { | 742 void ResourcePrefetchPredictor::RemoveAnEntryFromUrlDB() { |
| 678 if (url_table_cache_.empty()) | 743 if (url_table_cache_.empty()) |
| 679 return; | 744 return; |
| 680 | 745 |
| 746 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationEvent", | |
| 747 NAVIGATION_EVENT_URL_TABLE_FULL, | |
| 748 NAVIGATION_EVENT_COUNT); | |
| 749 | |
| 681 // TODO(shishir): Maybe use a heap to do this more efficiently. | 750 // TODO(shishir): Maybe use a heap to do this more efficiently. |
| 682 base::Time oldest_time; | 751 base::Time oldest_time; |
| 683 GURL url_to_erase; | 752 GURL url_to_erase; |
| 684 for (UrlTableCacheMap::iterator it = url_table_cache_.begin(); | 753 for (UrlTableCacheMap::iterator it = url_table_cache_.begin(); |
| 685 it != url_table_cache_.end(); ++it) { | 754 it != url_table_cache_.end(); ++it) { |
| 686 if (url_to_erase.is_empty() || it->second.last_visit < oldest_time) { | 755 if (url_to_erase.is_empty() || it->second.last_visit < oldest_time) { |
| 687 url_to_erase = it->first; | 756 url_to_erase = it->first; |
| 688 oldest_time = it->second.last_visit; | 757 oldest_time = it->second.last_visit; |
| 689 } | 758 } |
| 690 } | 759 } |
| 691 url_table_cache_.erase(url_to_erase); | 760 url_table_cache_.erase(url_to_erase); |
| 692 | 761 |
| 693 std::vector<GURL> urls_to_delete(1, url_to_erase); | 762 std::vector<GURL> urls_to_delete(1, url_to_erase); |
| 694 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 763 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, |
| 695 base::Bind(&ResourcePrefetchPredictorTables::DeleteRowsForUrls, | 764 base::Bind(&ResourcePrefetchPredictorTables::DeleteRowsForUrls, |
| 696 tables_, | 765 tables_, |
| 697 urls_to_delete)); | 766 urls_to_delete)); |
| 698 } | 767 } |
| 699 | 768 |
| 700 void ResourcePrefetchPredictor::MaybeReportAccuracyStats( | 769 void ResourcePrefetchPredictor::MaybeReportAccuracyStats( |
| 701 const NavigationID& navigation_id) const { | 770 const NavigationID& navigation_id) const { |
| 702 const GURL& main_frame_url = navigation_id.main_frame_url; | 771 const GURL& main_frame_url = navigation_id.main_frame_url; |
| 703 DCHECK(inflight_navigations_.find(navigation_id) != | 772 DCHECK(inflight_navigations_.find(navigation_id) != |
| 704 inflight_navigations_.end()); | 773 inflight_navigations_.end()); |
| 705 | 774 |
| 706 bool have_predictions_for_url = | 775 bool have_predictions_for_url = |
| 707 url_table_cache_.find(main_frame_url) != url_table_cache_.end(); | 776 url_table_cache_.find(main_frame_url) != url_table_cache_.end(); |
| 708 UMA_HISTOGRAM_BOOLEAN("ResourcePrefetchPredictor.HavePredictionsForUrl", | 777 if (have_predictions_for_url) { |
| 709 have_predictions_for_url); | 778 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationEvent", |
| 710 if (!have_predictions_for_url) | 779 NAVIGATION_EVENT_HAVE_PREDICTIONS_FOR_URL, |
| 780 NAVIGATION_EVENT_COUNT); | |
| 781 } else { | |
| 782 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationEvent", | |
| 783 NAVIGATION_EVENT_NO_PREDICTIONS_FOR_URL, | |
| 784 NAVIGATION_EVENT_COUNT); | |
| 711 return; | 785 return; |
| 786 } | |
| 712 | 787 |
| 713 const std::vector<URLRequestSummary>& actual = | 788 const std::vector<URLRequestSummary>& actual = |
| 714 inflight_navigations_.find(navigation_id)->second; | 789 inflight_navigations_.find(navigation_id)->second; |
| 715 const UrlTableRowVector& predicted = | 790 const UrlTableRowVector& predicted = |
| 716 url_table_cache_.find(main_frame_url)->second.rows; | 791 url_table_cache_.find(main_frame_url)->second.rows; |
| 717 | 792 |
| 718 std::map<GURL, bool> actual_resources; | 793 std::map<GURL, bool> actual_resources; |
| 794 int total_resources_fetched_from_network = 0; | |
| 719 for (std::vector<URLRequestSummary>::const_iterator it = actual.begin(); | 795 for (std::vector<URLRequestSummary>::const_iterator it = actual.begin(); |
| 720 it != actual.end(); ++it) { | 796 it != actual.end(); ++it) { |
| 721 actual_resources[it->resource_url] = it->was_cached; | 797 actual_resources[it->resource_url] = it->was_cached; |
| 798 if (!it->was_cached) | |
| 799 ++total_resources_fetched_from_network; | |
| 722 } | 800 } |
| 723 | 801 |
| 802 // Measure accuracy at 25, and 50 predicted resources. | |
| 724 int prefetch_cached = 0, prefetch_network = 0, prefetch_missed = 0; | 803 int prefetch_cached = 0, prefetch_network = 0, prefetch_missed = 0; |
| 725 int num_assumed_prefetched = std::min( | 804 int num_assumed_prefetched = std::min(static_cast<int>(predicted.size()), |
| 726 static_cast<int>(predicted.size()), | 805 50); |
| 727 config_.num_resources_assumed_prefetched); | |
| 728 for (int i = 0; i < num_assumed_prefetched; ++i) { | 806 for (int i = 0; i < num_assumed_prefetched; ++i) { |
| 729 const UrlTableRow& row = predicted[i]; | 807 const UrlTableRow& row = predicted[i]; |
| 730 if (actual_resources.find(row.resource_url) == actual_resources.end()) { | 808 std::map<GURL, bool>::const_iterator it = actual_resources.find( |
| 809 row.resource_url); | |
| 810 if (it == actual_resources.end()) { | |
| 731 ++prefetch_missed; | 811 ++prefetch_missed; |
| 732 } else if (actual_resources[row.resource_url]) { | 812 } else if (it->second) { |
| 733 ++prefetch_cached; | 813 ++prefetch_cached; |
| 734 } else { | 814 } else { |
| 735 ++prefetch_network; | 815 ++prefetch_network; |
| 736 } | 816 } |
| 817 | |
| 818 if ((num_assumed_prefetched < 25 && i == num_assumed_prefetched - 1) || | |
| 819 i == 24) { | |
| 820 UMA_HISTOGRAM_COUNTS( | |
|
dominich
2012/08/31 20:40:45
if you define a macro that takes 25 or 50 as a par
Shishir
2012/08/31 21:03:31
Wrote macros not to use the static initializer whi
| |
| 821 "ResourcePrefetchPredictor.PredictedPrefetchCount_25", | |
| 822 num_assumed_prefetched); | |
| 823 UMA_HISTOGRAM_COUNTS( | |
| 824 "ResourcePrefetchPredictor.PredictedPrefetchMisses_Count_25", | |
| 825 prefetch_missed); | |
| 826 UMA_HISTOGRAM_COUNTS( | |
| 827 "ResourcePrefetchPredictor.PredictedPrefetchFromCache_Count_25", | |
| 828 prefetch_cached); | |
| 829 UMA_HISTOGRAM_COUNTS( | |
| 830 "ResourcePrefetchPredictor.PredictedPrefetchFromNetwork_Count_25", | |
| 831 prefetch_network); | |
| 832 UMA_HISTOGRAM_PERCENTAGE( | |
| 833 "ResourcePrefetchPredictor.PredictedPrefetchMisses_" | |
| 834 "PercentOfTotalPrefetched_25", | |
| 835 prefetch_missed * 100.0 / (i + 1)); | |
| 836 UMA_HISTOGRAM_PERCENTAGE( | |
| 837 "ResourcePrefetchPredictor.PredictedPrefetchFromCache_" | |
| 838 "PercentOfTotalPrefetched_25", | |
| 839 prefetch_cached * 100.0 / (i + 1)); | |
| 840 UMA_HISTOGRAM_PERCENTAGE( | |
| 841 "ResourcePrefetchPredictor.PredictedPrefetchFromNetwork_" | |
| 842 "PercentOfTotalPrefetched_25", | |
| 843 prefetch_network * 100.0 / (i + 1)); | |
| 844 | |
| 845 // Measure the ratio of total number of resources prefetched from network | |
| 846 // vs the total number of resources fetched by the page from the network. | |
| 847 UMA_HISTOGRAM_PERCENTAGE( | |
| 848 "ResourcePrefetchPredictor." | |
| 849 "PredictedPrefetchFromNetworkPercentOfTotalFromNetwork_25", | |
| 850 prefetch_network * 100.0 / total_resources_fetched_from_network); | |
| 851 } | |
| 737 } | 852 } |
| 738 | 853 |
| 854 UMA_HISTOGRAM_COUNTS( | |
| 855 "ResourcePrefetchPredictor.PredictedPrefetchCount_50", | |
| 856 num_assumed_prefetched); | |
| 857 UMA_HISTOGRAM_COUNTS( | |
| 858 "ResourcePrefetchPredictor.PredictedPrefetchMisses_Count_50", | |
| 859 prefetch_missed); | |
| 860 UMA_HISTOGRAM_COUNTS( | |
| 861 "ResourcePrefetchPredictor.PredictedPrefetchFromCache_Count_50", | |
| 862 prefetch_cached); | |
| 863 UMA_HISTOGRAM_COUNTS( | |
| 864 "ResourcePrefetchPredictor.PredictedPrefetchFromNetwork_Count_50", | |
| 865 prefetch_network); | |
| 739 UMA_HISTOGRAM_PERCENTAGE( | 866 UMA_HISTOGRAM_PERCENTAGE( |
| 740 "ResourcePrefetchPredictor.PredictedPrefetchMisses", | 867 "ResourcePrefetchPredictor.PredictedPrefetchMisses_" |
| 868 "PercentOfTotalPrefetched_50", | |
| 741 prefetch_missed * 100.0 / num_assumed_prefetched); | 869 prefetch_missed * 100.0 / num_assumed_prefetched); |
| 742 UMA_HISTOGRAM_PERCENTAGE( | 870 UMA_HISTOGRAM_PERCENTAGE( |
| 743 "ResourcePrefetchPredictor.PredictedPrefetchFromCache", | 871 "ResourcePrefetchPredictor.PredictedPrefetchFromCache_" |
| 872 "PercentOfTotalPrefetched_50", | |
| 744 prefetch_cached * 100.0 / num_assumed_prefetched); | 873 prefetch_cached * 100.0 / num_assumed_prefetched); |
| 745 UMA_HISTOGRAM_PERCENTAGE( | 874 UMA_HISTOGRAM_PERCENTAGE( |
| 746 "ResourcePrefetchPredictor.PredictedPrefetchFromNetwork", | 875 "ResourcePrefetchPredictor.PredictedPrefetchFromNetwork_" |
| 876 "PercentOfTotalPrefetched_50", | |
| 747 prefetch_network * 100.0 / num_assumed_prefetched); | 877 prefetch_network * 100.0 / num_assumed_prefetched); |
| 878 | |
| 879 // Measure the ratio of total number of resources prefetched from network vs | |
| 880 // the total number of resources fetched by the page from the network. | |
| 881 UMA_HISTOGRAM_PERCENTAGE( | |
| 882 "ResourcePrefetchPredictor." | |
| 883 "PredictedPrefetchFromNetworkPercentOfTotalFromNetwork_50", | |
| 884 prefetch_network * 100.0 / total_resources_fetched_from_network); | |
| 748 } | 885 } |
| 749 | 886 |
| 750 void ResourcePrefetchPredictor::DeleteAllUrls() { | 887 void ResourcePrefetchPredictor::DeleteAllUrls() { |
| 751 inflight_navigations_.clear(); | 888 inflight_navigations_.clear(); |
| 752 url_table_cache_.clear(); | 889 url_table_cache_.clear(); |
| 753 | 890 |
| 754 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, | 891 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, |
| 755 base::Bind(&ResourcePrefetchPredictorTables::DeleteAllRows, tables_)); | 892 base::Bind(&ResourcePrefetchPredictorTables::DeleteAllRows, tables_)); |
| 756 } | 893 } |
| 757 | 894 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 774 tables_, | 911 tables_, |
| 775 urls_to_delete)); | 912 urls_to_delete)); |
| 776 } | 913 } |
| 777 | 914 |
| 778 void ResourcePrefetchPredictor::SetTablesForTesting( | 915 void ResourcePrefetchPredictor::SetTablesForTesting( |
| 779 scoped_refptr<ResourcePrefetchPredictorTables> tables) { | 916 scoped_refptr<ResourcePrefetchPredictorTables> tables) { |
| 780 tables_ = tables; | 917 tables_ = tables; |
| 781 } | 918 } |
| 782 | 919 |
| 783 } // namespace predictors | 920 } // namespace predictors |
| OLD | NEW |