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