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

Side by Side Diff: chrome/browser/history/top_sites.cc

Issue 4106014: Tweaks to improve memory consumption by TopSites. The biggest culprit (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Incorporate review feedback Created 10 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « chrome/browser/history/top_sites.h ('k') | chrome/browser/history/top_sites_cache.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 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/history/top_sites.h" 5 #include "chrome/browser/history/top_sites.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 9
10 #include "app/l10n_util.h" 10 #include "app/l10n_util.h"
(...skipping 21 matching lines...) Expand all
32 #include "gfx/codec/jpeg_codec.h" 32 #include "gfx/codec/jpeg_codec.h"
33 #include "grit/chromium_strings.h" 33 #include "grit/chromium_strings.h"
34 #include "grit/generated_resources.h" 34 #include "grit/generated_resources.h"
35 #include "grit/locale_settings.h" 35 #include "grit/locale_settings.h"
36 #include "third_party/skia/include/core/SkBitmap.h" 36 #include "third_party/skia/include/core/SkBitmap.h"
37 37
38 namespace history { 38 namespace history {
39 39
40 // How many top sites to store in the cache. 40 // How many top sites to store in the cache.
41 static const size_t kTopSitesNumber = 20; 41 static const size_t kTopSitesNumber = 20;
42
43 // Max number of temporary images we'll cache. See comment above
44 // temp_images_ for details.
45 static const size_t kMaxTempTopImages = 8;
46
42 static const size_t kTopSitesShown = 8; 47 static const size_t kTopSitesShown = 8;
43 static const int kDaysOfHistory = 90; 48 static const int kDaysOfHistory = 90;
44 // Time from startup to first HistoryService query. 49 // Time from startup to first HistoryService query.
45 static const int64 kUpdateIntervalSecs = 15; 50 static const int64 kUpdateIntervalSecs = 15;
46 // Intervals between requests to HistoryService. 51 // Intervals between requests to HistoryService.
47 static const int64 kMinUpdateIntervalMinutes = 1; 52 static const int64 kMinUpdateIntervalMinutes = 1;
48 static const int64 kMaxUpdateIntervalMinutes = 60; 53 static const int64 kMaxUpdateIntervalMinutes = 60;
49 54
50 // IDs of the sites we force into top sites. 55 // IDs of the sites we force into top sites.
51 static const int kPrepopulatePageIDs[] = 56 static const int kPrepopulatePageIDs[] =
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 } 198 }
194 199
195 if (!HistoryService::CanAddURL(url)) 200 if (!HistoryService::CanAddURL(url))
196 return false; // It's not a real webpage. 201 return false; // It's not a real webpage.
197 202
198 scoped_refptr<RefCountedBytes> thumbnail_data; 203 scoped_refptr<RefCountedBytes> thumbnail_data;
199 if (!EncodeBitmap(thumbnail, &thumbnail_data)) 204 if (!EncodeBitmap(thumbnail, &thumbnail_data))
200 return false; 205 return false;
201 206
202 if (add_temp_thumbnail) { 207 if (add_temp_thumbnail) {
208 // Always remove the existing entry and then add it back. That way if we end
209 // up with too many temp thumbnails we'll prune the oldest first.
210 RemoveTemporaryThumbnailByURL(url);
203 AddTemporaryThumbnail(url, thumbnail_data, score); 211 AddTemporaryThumbnail(url, thumbnail_data, score);
204 return true; 212 return true;
205 } 213 }
206 214
207 return SetPageThumbnailEncoded(url, thumbnail_data, score); 215 return SetPageThumbnailEncoded(url, thumbnail_data, score);
208 } 216 }
209 217
210 void TopSites::GetMostVisitedURLs(CancelableRequestConsumer* consumer, 218 void TopSites::GetMostVisitedURLs(CancelableRequestConsumer* consumer,
211 GetTopSitesCallback* callback) { 219 GetTopSitesCallback* callback) {
212 // WARNING: this may be invoked on any thread. 220 // WARNING: this may be invoked on any thread.
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 index, 488 index,
481 *(cache_->GetImage(most_visited.url))); 489 *(cache_->GetImage(most_visited.url)));
482 return true; 490 return true;
483 } 491 }
484 492
485 // static 493 // static
486 bool TopSites::EncodeBitmap(const SkBitmap& bitmap, 494 bool TopSites::EncodeBitmap(const SkBitmap& bitmap,
487 scoped_refptr<RefCountedBytes>* bytes) { 495 scoped_refptr<RefCountedBytes>* bytes) {
488 *bytes = new RefCountedBytes(); 496 *bytes = new RefCountedBytes();
489 SkAutoLockPixels bitmap_lock(bitmap); 497 SkAutoLockPixels bitmap_lock(bitmap);
490 return gfx::JPEGCodec::Encode( 498 std::vector<unsigned char> data;
491 reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)), 499 if (!gfx::JPEGCodec::Encode(
492 gfx::JPEGCodec::FORMAT_BGRA, bitmap.width(), 500 reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)),
493 bitmap.height(), 501 gfx::JPEGCodec::FORMAT_BGRA, bitmap.width(),
494 static_cast<int>(bitmap.rowBytes()), 90, 502 bitmap.height(),
495 &((*bytes)->data)); 503 static_cast<int>(bitmap.rowBytes()), 90,
504 &data)) {
505 return false;
506 }
507 // As we're going to cache this data, make sure the vector is only as big as
508 // it needs to be.
509 (*bytes)->data = data;
510 return true;
511 }
512
513 void TopSites::RemoveTemporaryThumbnailByURL(const GURL& url) {
514 for (TempImages::iterator i = temp_images_.begin(); i != temp_images_.end();
515 ++i) {
516 if (i->first == url) {
517 temp_images_.erase(i);
518 return;
519 }
520 }
496 } 521 }
497 522
498 void TopSites::AddTemporaryThumbnail(const GURL& url, 523 void TopSites::AddTemporaryThumbnail(const GURL& url,
499 const RefCountedBytes* thumbnail, 524 const RefCountedBytes* thumbnail,
500 const ThumbnailScore& score) { 525 const ThumbnailScore& score) {
501 Images& img = temp_thumbnails_map_[url]; 526 if (temp_images_.size() == kMaxTempTopImages)
502 img.thumbnail = const_cast<RefCountedBytes*>(thumbnail); 527 temp_images_.erase(temp_images_.begin());
503 img.thumbnail_score = score; 528
529 TempImage image;
530 image.first = url;
531 image.second.thumbnail = const_cast<RefCountedBytes*>(thumbnail);
532 image.second.thumbnail_score = score;
533 temp_images_.push_back(image);
504 } 534 }
505 535
506 void TopSites::StartQueryForMostVisited() { 536 void TopSites::StartQueryForMostVisited() {
507 if (!profile_) 537 if (!profile_)
508 return; 538 return;
509 539
510 HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); 540 HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
511 // |hs| may be null during unit tests. 541 // |hs| may be null during unit tests.
512 if (hs) { 542 if (hs) {
513 hs->QueryMostVisitedURLs( 543 hs->QueryMostVisitedURLs(
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
696 } 726 }
697 StartQueryForMostVisited(); 727 StartQueryForMostVisited();
698 } else if (type == NotificationType::NAV_ENTRY_COMMITTED) { 728 } else if (type == NotificationType::NAV_ENTRY_COMMITTED) {
699 if (cache_->top_sites().size() < kTopSitesNumber) { 729 if (cache_->top_sites().size() < kTopSitesNumber) {
700 NavigationController::LoadCommittedDetails* load_details = 730 NavigationController::LoadCommittedDetails* load_details =
701 Details<NavigationController::LoadCommittedDetails>(details).ptr(); 731 Details<NavigationController::LoadCommittedDetails>(details).ptr();
702 if (!load_details) 732 if (!load_details)
703 return; 733 return;
704 const GURL& url = load_details->entry->url(); 734 const GURL& url = load_details->entry->url();
705 if (!cache_->IsKnownURL(url) && HistoryService::CanAddURL(url)) { 735 if (!cache_->IsKnownURL(url) && HistoryService::CanAddURL(url)) {
706 // Ideally we would just invoke StartQueryForMostVisited, but at the 736 // To avoid slamming history we throttle requests when the url updates.
707 // time this is invoked history hasn't been updated, which means if we 737 // To do otherwise negatively impacts perf tests.
708 // invoked StartQueryForMostVisited now we could get stale data. 738 RestartQueryForTopSitesTimer(GetUpdateDelay());
709 RestartQueryForTopSitesTimer(base::TimeDelta::FromMilliseconds(1));
710 } 739 }
711 } 740 }
712 } 741 }
713 } 742 }
714 743
715 void TopSites::SetTopSites(const MostVisitedURLList& new_top_sites) { 744 void TopSites::SetTopSites(const MostVisitedURLList& new_top_sites) {
716 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 745 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
717 746
718 MostVisitedURLList top_sites(new_top_sites); 747 MostVisitedURLList top_sites(new_top_sites);
719 AddPrepopulatedPages(&top_sites); 748 AddPrepopulatedPages(&top_sites);
720 749
721 TopSitesDelta delta; 750 TopSitesDelta delta;
722 DiffMostVisited(cache_->top_sites(), top_sites, &delta); 751 DiffMostVisited(cache_->top_sites(), top_sites, &delta);
723 if (!delta.deleted.empty() || !delta.added.empty() || !delta.moved.empty()) 752 if (!delta.deleted.empty() || !delta.added.empty() || !delta.moved.empty())
724 backend_->UpdateTopSites(delta); 753 backend_->UpdateTopSites(delta);
725 754
726 last_num_urls_changed_ = delta.added.size() + delta.moved.size(); 755 last_num_urls_changed_ = delta.added.size() + delta.moved.size();
727 756
728 // We always do the following steps (setting top sites in cache, and resetting 757 // We always do the following steps (setting top sites in cache, and resetting
729 // thread safe cache ...) as this method is invoked during startup at which 758 // thread safe cache ...) as this method is invoked during startup at which
730 // point the caches haven't been updated yet. 759 // point the caches haven't been updated yet.
731 cache_->SetTopSites(top_sites); 760 cache_->SetTopSites(top_sites);
732 761
733 // See if we have any tmp thumbnails for the new sites. 762 // See if we have any tmp thumbnails for the new sites.
734 if (!temp_thumbnails_map_.empty()) { 763 if (!temp_images_.empty()) {
735 for (size_t i = 0; i < top_sites.size(); ++i) { 764 for (size_t i = 0; i < top_sites.size(); ++i) {
736 const MostVisitedURL& mv = top_sites[i]; 765 const MostVisitedURL& mv = top_sites[i];
737 GURL canonical_url = cache_->GetCanonicalURL(mv.url); 766 GURL canonical_url = cache_->GetCanonicalURL(mv.url);
738 for (std::map<GURL, Images>::iterator it = temp_thumbnails_map_.begin(); 767 // At the time we get the thumbnail redirects aren't known, so we have to
739 it != temp_thumbnails_map_.end(); ++it) { 768 // iterate through all the images.
740 // Must map all temp URLs to canonical ones. 769 for (TempImages::iterator it = temp_images_.begin();
741 // temp_thumbnails_map_ contains non-canonical URLs, because 770 it != temp_images_.end(); ++it) {
742 // when we add a temp thumbnail, redirect chain is not known.
743 // This is slow, but temp_thumbnails_map_ should have very few URLs.
744 if (canonical_url == cache_->GetCanonicalURL(it->first)) { 771 if (canonical_url == cache_->GetCanonicalURL(it->first)) {
745 SetPageThumbnailEncoded(mv.url, 772 SetPageThumbnailEncoded(mv.url,
746 it->second.thumbnail, 773 it->second.thumbnail,
747 it->second.thumbnail_score); 774 it->second.thumbnail_score);
748 temp_thumbnails_map_.erase(it); 775 temp_images_.erase(it);
749 break; 776 break;
750 } 777 }
751 } 778 }
752 } 779 }
753 } 780 }
754 781
755 if (top_sites.size() >= kTopSitesNumber) 782 if (top_sites.size() >= kTopSitesNumber)
756 temp_thumbnails_map_.clear(); 783 temp_images_.clear();
757 784
758 ResetThreadSafeCache(); 785 ResetThreadSafeCache();
759 ResetThreadSafeImageCache(); 786 ResetThreadSafeImageCache();
760 787
761 // Restart the timer that queries history for top sites. This is done to 788 // Restart the timer that queries history for top sites. This is done to
762 // ensure we stay in sync with history. 789 // ensure we stay in sync with history.
763 RestartQueryForTopSitesTimer(GetUpdateDelay()); 790 RestartQueryForTopSitesTimer(GetUpdateDelay());
764 } 791 }
765 792
766 int TopSites::num_results_to_request_from_history() const { 793 int TopSites::num_results_to_request_from_history() const {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
803 thread_safe_cache_->SetTopSites(cached); 830 thread_safe_cache_->SetTopSites(cached);
804 } 831 }
805 832
806 void TopSites::ResetThreadSafeImageCache() { 833 void TopSites::ResetThreadSafeImageCache() {
807 AutoLock lock(lock_); 834 AutoLock lock(lock_);
808 thread_safe_cache_->SetThumbnails(cache_->images()); 835 thread_safe_cache_->SetThumbnails(cache_->images());
809 thread_safe_cache_->RemoveUnreferencedThumbnails(); 836 thread_safe_cache_->RemoveUnreferencedThumbnails();
810 } 837 }
811 838
812 void TopSites::RestartQueryForTopSitesTimer(base::TimeDelta delta) { 839 void TopSites::RestartQueryForTopSitesTimer(base::TimeDelta delta) {
840 if (timer_.IsRunning() && ((timer_start_time_ + timer_.GetCurrentDelay()) <
841 (base::TimeTicks::Now() + delta))) {
842 return;
843 }
844
845 timer_start_time_ = base::TimeTicks::Now();
813 timer_.Stop(); 846 timer_.Stop();
814 timer_.Start(delta, this, &TopSites::StartQueryForMostVisited); 847 timer_.Start(delta, this, &TopSites::StartQueryForMostVisited);
815 } 848 }
816 849
817 void TopSites::OnHistoryMigrationWrittenToDisk(TopSitesBackend::Handle handle) { 850 void TopSites::OnHistoryMigrationWrittenToDisk(TopSitesBackend::Handle handle) {
818 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 851 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
819 852
820 if (!profile_) 853 if (!profile_)
821 return; 854 return;
822 855
(...skipping 28 matching lines...) Expand all
851 base::TimeDelta::FromSeconds(kUpdateIntervalSecs)); 884 base::TimeDelta::FromSeconds(kUpdateIntervalSecs));
852 } else { 885 } else {
853 // The top sites file didn't exist or is the wrong version. We need to wait 886 // The top sites file didn't exist or is the wrong version. We need to wait
854 // for history to finish loading to know if we really needed to migrate. 887 // for history to finish loading to know if we really needed to migrate.
855 if (history_state_ == HISTORY_LOADED) { 888 if (history_state_ == HISTORY_LOADED) {
856 top_sites_state_ = TOP_SITES_LOADED; 889 top_sites_state_ = TOP_SITES_LOADED;
857 SetTopSites(MostVisitedURLList()); 890 SetTopSites(MostVisitedURLList());
858 MoveStateToLoaded(); 891 MoveStateToLoaded();
859 } else { 892 } else {
860 top_sites_state_ = TOP_SITES_LOADED_WAITING_FOR_HISTORY; 893 top_sites_state_ = TOP_SITES_LOADED_WAITING_FOR_HISTORY;
861 // Ask for history just in case it hasn't been load yet. When history 894 // Ask for history just in case it hasn't been loaded yet. When history
862 // finishes loading we'll do migration and/or move to loaded. 895 // finishes loading we'll do migration and/or move to loaded.
863 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); 896 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
864 } 897 }
865 } 898 }
866 } 899 }
867 900
868 void TopSites::OnTopSitesAvailableFromHistory( 901 void TopSites::OnTopSitesAvailableFromHistory(
869 CancelableRequestProvider::Handle handle, 902 CancelableRequestProvider::Handle handle,
870 MostVisitedURLList pages) { 903 MostVisitedURLList pages) {
871 SetTopSites(pages); 904 SetTopSites(pages);
872 } 905 }
873 906
874 } // namespace history 907 } // namespace history
OLDNEW
« no previous file with comments | « chrome/browser/history/top_sites.h ('k') | chrome/browser/history/top_sites_cache.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698