summaryrefslogtreecommitdiffstats
path: root/chrome/browser/history
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/history')
-rw-r--r--chrome/browser/history/thumbnail_database.cc19
-rw-r--r--chrome/browser/history/top_sites.cc79
-rw-r--r--chrome/browser/history/top_sites.h16
-rw-r--r--chrome/browser/history/top_sites_cache.cc26
-rw-r--r--chrome/browser/history/top_sites_cache.h34
-rw-r--r--chrome/browser/history/top_sites_database.cc4
6 files changed, 126 insertions, 52 deletions
diff --git a/chrome/browser/history/thumbnail_database.cc b/chrome/browser/history/thumbnail_database.cc
index e615876..e1054ac 100644
--- a/chrome/browser/history/thumbnail_database.cc
+++ b/chrome/browser/history/thumbnail_database.cc
@@ -104,21 +104,10 @@ sql::InitStatus ThumbnailDatabase::OpenDatabase(sql::Connection* db,
// Set the exceptional sqlite error handler.
db->set_error_delegate(GetErrorHandlerForThumbnailDb());
- // Set the database page size to something larger to give us
- // better performance (we're typically seek rather than bandwidth limited).
- // This only has an effect before any tables have been created, otherwise
- // this is a NOP. Must be a power of 2 and a max of 8192. We use a bigger
- // one because we're storing larger data (4-16K) in it, so we want a few
- // blocks per element.
- db->set_page_size(4096);
-
- // The UI is generally designed to work well when the thumbnail database is
- // slow, so we can tolerate much less caching. The file is also very large
- // and so caching won't save a significant percentage of it for us,
- // reducing the benefit of caching in the first place. With the default cache
- // size of 2000 pages, it will take >8MB of memory, so reducing it can be a
- // big savings.
- db->set_cache_size(64);
+ // Thumbnails db now only stores favicons, so we don't need that big a page
+ // size or cache.
+ db->set_page_size(2048);
+ db->set_cache_size(32);
// Run the database in exclusive mode. Nobody else should be accessing the
// database while we're running, and this will give somewhat improved perf.
diff --git a/chrome/browser/history/top_sites.cc b/chrome/browser/history/top_sites.cc
index 1dacd3b..8bdfe34 100644
--- a/chrome/browser/history/top_sites.cc
+++ b/chrome/browser/history/top_sites.cc
@@ -39,6 +39,11 @@ namespace history {
// How many top sites to store in the cache.
static const size_t kTopSitesNumber = 20;
+
+// Max number of temporary images we'll cache. See comment above
+// temp_images_ for details.
+static const size_t kMaxTempTopImages = 8;
+
static const size_t kTopSitesShown = 8;
static const int kDaysOfHistory = 90;
// Time from startup to first HistoryService query.
@@ -200,6 +205,9 @@ bool TopSites::SetPageThumbnail(const GURL& url,
return false;
if (add_temp_thumbnail) {
+ // Always remove the existing entry and then add it back. That way if we end
+ // up with too many temp thumbnails we'll prune the oldest first.
+ RemoveTemporaryThumbnailByURL(url);
AddTemporaryThumbnail(url, thumbnail_data, score);
return true;
}
@@ -487,20 +495,42 @@ bool TopSites::EncodeBitmap(const SkBitmap& bitmap,
scoped_refptr<RefCountedBytes>* bytes) {
*bytes = new RefCountedBytes();
SkAutoLockPixels bitmap_lock(bitmap);
- return gfx::JPEGCodec::Encode(
- reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)),
- gfx::JPEGCodec::FORMAT_BGRA, bitmap.width(),
- bitmap.height(),
- static_cast<int>(bitmap.rowBytes()), 90,
- &((*bytes)->data));
+ std::vector<unsigned char> data;
+ if (!gfx::JPEGCodec::Encode(
+ reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)),
+ gfx::JPEGCodec::FORMAT_BGRA, bitmap.width(),
+ bitmap.height(),
+ static_cast<int>(bitmap.rowBytes()), 90,
+ &data)) {
+ return false;
+ }
+ // As we're going to cache this data, make sure the vector is only as big as
+ // it needs to be.
+ (*bytes)->data = data;
+ return true;
+}
+
+void TopSites::RemoveTemporaryThumbnailByURL(const GURL& url) {
+ for (TempImages::iterator i = temp_images_.begin(); i != temp_images_.end();
+ ++i) {
+ if (i->first == url) {
+ temp_images_.erase(i);
+ return;
+ }
+ }
}
void TopSites::AddTemporaryThumbnail(const GURL& url,
const RefCountedBytes* thumbnail,
const ThumbnailScore& score) {
- Images& img = temp_thumbnails_map_[url];
- img.thumbnail = const_cast<RefCountedBytes*>(thumbnail);
- img.thumbnail_score = score;
+ if (temp_images_.size() == kMaxTempTopImages)
+ temp_images_.erase(temp_images_.begin());
+
+ TempImage image;
+ image.first = url;
+ image.second.thumbnail = const_cast<RefCountedBytes*>(thumbnail);
+ image.second.thumbnail_score = score;
+ temp_images_.push_back(image);
}
void TopSites::StartQueryForMostVisited() {
@@ -703,10 +733,9 @@ void TopSites::Observe(NotificationType type,
return;
const GURL& url = load_details->entry->url();
if (!cache_->IsKnownURL(url) && HistoryService::CanAddURL(url)) {
- // Ideally we would just invoke StartQueryForMostVisited, but at the
- // time this is invoked history hasn't been updated, which means if we
- // invoked StartQueryForMostVisited now we could get stale data.
- RestartQueryForTopSitesTimer(base::TimeDelta::FromMilliseconds(1));
+ // To avoid slamming history we throttle requests when the url updates.
+ // To do otherwise negatively impacts perf tests.
+ RestartQueryForTopSitesTimer(GetUpdateDelay());
}
}
}
@@ -731,21 +760,19 @@ void TopSites::SetTopSites(const MostVisitedURLList& new_top_sites) {
cache_->SetTopSites(top_sites);
// See if we have any tmp thumbnails for the new sites.
- if (!temp_thumbnails_map_.empty()) {
+ if (!temp_images_.empty()) {
for (size_t i = 0; i < top_sites.size(); ++i) {
const MostVisitedURL& mv = top_sites[i];
GURL canonical_url = cache_->GetCanonicalURL(mv.url);
- for (std::map<GURL, Images>::iterator it = temp_thumbnails_map_.begin();
- it != temp_thumbnails_map_.end(); ++it) {
- // Must map all temp URLs to canonical ones.
- // temp_thumbnails_map_ contains non-canonical URLs, because
- // when we add a temp thumbnail, redirect chain is not known.
- // This is slow, but temp_thumbnails_map_ should have very few URLs.
+ // At the time we get the thumbnail redirects aren't known, so we have to
+ // iterate through all the images.
+ for (TempImages::iterator it = temp_images_.begin();
+ it != temp_images_.end(); ++it) {
if (canonical_url == cache_->GetCanonicalURL(it->first)) {
SetPageThumbnailEncoded(mv.url,
it->second.thumbnail,
it->second.thumbnail_score);
- temp_thumbnails_map_.erase(it);
+ temp_images_.erase(it);
break;
}
}
@@ -753,7 +780,7 @@ void TopSites::SetTopSites(const MostVisitedURLList& new_top_sites) {
}
if (top_sites.size() >= kTopSitesNumber)
- temp_thumbnails_map_.clear();
+ temp_images_.clear();
ResetThreadSafeCache();
ResetThreadSafeImageCache();
@@ -810,6 +837,12 @@ void TopSites::ResetThreadSafeImageCache() {
}
void TopSites::RestartQueryForTopSitesTimer(base::TimeDelta delta) {
+ if (timer_.IsRunning() && ((timer_start_time_ + timer_.GetCurrentDelay()) <
+ (base::TimeTicks::Now() + delta))) {
+ return;
+ }
+
+ timer_start_time_ = base::TimeTicks::Now();
timer_.Stop();
timer_.Start(delta, this, &TopSites::StartQueryForMostVisited);
}
@@ -858,7 +891,7 @@ void TopSites::OnGotMostVisitedThumbnails(
MoveStateToLoaded();
} else {
top_sites_state_ = TOP_SITES_LOADED_WAITING_FOR_HISTORY;
- // Ask for history just in case it hasn't been load yet. When history
+ // Ask for history just in case it hasn't been loaded yet. When history
// finishes loading we'll do migration and/or move to loaded.
profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
}
diff --git a/chrome/browser/history/top_sites.h b/chrome/browser/history/top_sites.h
index cc70cc7..bd406f1 100644
--- a/chrome/browser/history/top_sites.h
+++ b/chrome/browser/history/top_sites.h
@@ -6,14 +6,14 @@
#define CHROME_BROWSER_HISTORY_TOP_SITES_H_
#pragma once
-#include <map>
+#include <list>
#include <set>
#include <string>
-#include <vector>
#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/lock.h"
+#include "base/time.h"
#include "base/timer.h"
#include "base/ref_counted.h"
#include "base/ref_counted_memory.h"
@@ -145,6 +145,9 @@ class TopSites
friend class base::RefCountedThreadSafe<TopSites>;
friend class TopSitesTest;
+ typedef std::pair<GURL, Images> TempImage;
+ typedef std::list<TempImage> TempImages;
+
// Enumeration of the possible states history can be in.
enum HistoryLoadState {
// We're waiting for history to finish loading.
@@ -191,6 +194,10 @@ class TopSites
static bool EncodeBitmap(const SkBitmap& bitmap,
scoped_refptr<RefCountedBytes>* bytes);
+ // Removes the cached thumbnail for url. Does nothing if |url| if not cached
+ // in |temp_images_|.
+ void RemoveTemporaryThumbnailByURL(const GURL& url);
+
// Add a thumbnail for an unknown url. See temp_thumbnails_map_.
void AddTemporaryThumbnail(const GURL& url,
const RefCountedBytes* thumbnail,
@@ -295,6 +302,9 @@ class TopSites
// data stays in sync with history.
base::OneShotTimer<TopSites> timer_;
+ // The time we started |timer_| at. Only valid if |timer_| is running.
+ base::TimeTicks timer_start_time_;
+
NotificationRegistrar registrar_;
// The number of URLs changed on the last update.
@@ -309,7 +319,7 @@ class TopSites
// called, if we don't know about that URL yet and we don't have
// enough Top Sites (new profile), we store it until the next
// SetTopSites call.
- URLToImagesMap temp_thumbnails_map_;
+ TempImages temp_images_;
// Blacklisted and pinned URLs are stored in Preferences.
diff --git a/chrome/browser/history/top_sites_cache.cc b/chrome/browser/history/top_sites_cache.cc
index 9bae928..828b7014 100644
--- a/chrome/browser/history/top_sites_cache.cc
+++ b/chrome/browser/history/top_sites_cache.cc
@@ -48,17 +48,17 @@ bool TopSitesCache::GetPageThumbnail(const GURL& url,
}
GURL TopSitesCache::GetCanonicalURL(const GURL& url) {
- std::map<GURL, size_t>::const_iterator i = canonical_urls_.find(url);
- return i == canonical_urls_.end() ? url : top_sites_[i->second].url;
+ CanonicalURLs::iterator i = TopSitesCache::GetCanonicalURLsIterator(url);
+ return i == canonical_urls_.end() ? url : i->first.first->url;
}
bool TopSitesCache::IsKnownURL(const GURL& url) {
- return canonical_urls_.find(url) != canonical_urls_.end();
+ return GetCanonicalURLsIterator(url) != canonical_urls_.end();
}
size_t TopSitesCache::GetURLIndex(const GURL& url) {
DCHECK(IsKnownURL(url));
- return canonical_urls_[url];
+ return GetCanonicalURLsIterator(url)->second;
}
void TopSitesCache::RemoveUnreferencedThumbnails() {
@@ -88,9 +88,23 @@ void TopSitesCache::StoreRedirectChain(const RedirectList& redirects,
// Map all the redirected URLs to the destination.
for (size_t i = 0; i < redirects.size(); i++) {
// If this redirect is already known, don't replace it with a new one.
- if (canonical_urls_.find(redirects[i]) == canonical_urls_.end())
- canonical_urls_[redirects[i]] = destination;
+ if (!IsKnownURL(redirects[i])) {
+ CanonicalURLEntry entry;
+ entry.first = &(top_sites_[destination]);
+ entry.second = i;
+ canonical_urls_[entry] = destination;
+ }
}
}
+TopSitesCache::CanonicalURLs::iterator TopSitesCache::GetCanonicalURLsIterator(
+ const GURL& url) {
+ MostVisitedURL most_visited_url;
+ most_visited_url.redirects.push_back(url);
+ CanonicalURLEntry entry;
+ entry.first = &most_visited_url;
+ entry.second = 0u;
+ return canonical_urls_.find(entry);
+}
+
} // namespace history
diff --git a/chrome/browser/history/top_sites_cache.h b/chrome/browser/history/top_sites_cache.h
index 7cedd9f..4c5d79a 100644
--- a/chrome/browser/history/top_sites_cache.h
+++ b/chrome/browser/history/top_sites_cache.h
@@ -6,7 +6,9 @@
#define CHROME_BROWSER_HISTORY_TOP_SITES_CACHE_H_
#pragma once
+#include <algorithm>
#include <map>
+#include <string>
#include "base/ref_counted.h"
#include "chrome/browser/history/history_types.h"
@@ -56,21 +58,47 @@ class TopSitesCache {
void RemoveUnreferencedThumbnails();
private:
+ // The entries in CanonicalURLs, see CanonicalURLs for details. The second
+ // argument gives the index of the URL into MostVisitedURLs redirects.
+ typedef std::pair<MostVisitedURL*, size_t> CanonicalURLEntry;
+
+ // Comparator used for CanonicalURLs.
+ class CanonicalURLComparator {
+ public:
+ bool operator()(const CanonicalURLEntry& e1,
+ const CanonicalURLEntry& e2) const {
+ return e1.first->redirects[e1.second] < e2.first->redirects[e2.second];
+ }
+ };
+
+ // This is used to map from redirect url to the MostVisitedURL the redirect is
+ // from. Ideally this would be map<GURL, size_t> (second param indexing into
+ // top_sites_), but this results in duplicating all redirect urls. As some
+ // sites have a lot of redirects, we instead use the MostVisitedURL* and the
+ // index of the redirect as the key, and the index into top_sites_ as the
+ // value. This way we aren't duplicating GURLs. CanonicalURLComparator
+ // enforces the ordering as if we were using GURLs.
+ typedef std::map<CanonicalURLEntry, size_t,
+ CanonicalURLComparator> CanonicalURLs;
+
// Generates the set of canonical urls from |top_sites_|.
void GenerateCanonicalURLs();
// Stores a set of redirects. This is used by GenerateCanonicalURLs.
void StoreRedirectChain(const RedirectList& redirects, size_t destination);
+ // Returns the iterator into canconical_urls_ for the specified url.
+ CanonicalURLs::iterator GetCanonicalURLsIterator(const GURL& url);
+
// The top sites.
MostVisitedURLList top_sites_;
// The images. These map from canonical url to image.
URLToImagesMap images_;
- // Generated from the redirects to and from the most visited pages, this maps
- // the redirects to the index into top_sites_ that contains it.
- std::map<GURL, size_t> canonical_urls_;
+ // Generated from the redirects to and from the most visited pages. See
+ // description above typedef for details.
+ CanonicalURLs canonical_urls_;
DISALLOW_COPY_AND_ASSIGN(TopSitesCache);
};
diff --git a/chrome/browser/history/top_sites_database.cc b/chrome/browser/history/top_sites_database.cc
index 4c751bd..1058d22 100644
--- a/chrome/browser/history/top_sites_database.cc
+++ b/chrome/browser/history/top_sites_database.cc
@@ -132,7 +132,7 @@ std::string TopSitesDatabase::GetRedirects(const MostVisitedURL& url) {
// static
void TopSitesDatabase::SetRedirects(const std::string& redirects,
- MostVisitedURL* url) {
+ MostVisitedURL* url) {
std::vector<std::string> redirects_vector;
SplitStringAlongWhitespace(redirects, &redirects_vector);
for (size_t i = 0; i < redirects_vector.size(); i++)
@@ -366,7 +366,7 @@ sql::Connection* TopSitesDatabase::CreateDB(const FilePath& db_name) {
// Settings copied from ThumbnailDatabase.
db->set_error_delegate(GetErrorHandlerForThumbnailDb());
db->set_page_size(4096);
- db->set_cache_size(64);
+ db->set_cache_size(32);
if (!db->Open(db_name)) {
LOG(ERROR) << db->GetErrorMessage();