Commit 6e422cde authored by Alexei Filippov's avatar Alexei Filippov Committed by Commit Bot

Refactor: avoid vectors copying in TopSitesImpl

There's no change to semantics.
- got rid of ref-counted MostVisitedThreadSafe
- made extensive use of movable vectors

BUG=1006830

Change-Id: Iba70c2955f01ceaeac8771ca93af2258829f02a2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1819037Reviewed-by: default avatarScott Violet <sky@chromium.org>
Commit-Queue: Alexei Filippov <alph@chromium.org>
Cr-Commit-Position: refs/heads/master@{#699049}
parent adda5b83
...@@ -425,8 +425,6 @@ struct TopSitesDelta { ...@@ -425,8 +425,6 @@ struct TopSitesDelta {
MostVisitedURLWithRankList moved; MostVisitedURLWithRankList moved;
}; };
typedef base::RefCountedData<MostVisitedURLList> MostVisitedThreadSafe;
// Map from origins to a count of matching URLs and the last visited time to any // Map from origins to a count of matching URLs and the last visited time to any
// URL under that origin. // URL under that origin.
typedef std::map<GURL, std::pair<int, base::Time>> OriginCountAndLastVisitMap; typedef std::map<GURL, std::pair<int, base::Time>> OriginCountAndLastVisitMap;
......
...@@ -46,12 +46,10 @@ void TopSitesBackend::Shutdown() { ...@@ -46,12 +46,10 @@ void TopSitesBackend::Shutdown() {
void TopSitesBackend::GetMostVisitedSites( void TopSitesBackend::GetMostVisitedSites(
GetMostVisitedSitesCallback callback, GetMostVisitedSitesCallback callback,
base::CancelableTaskTracker* tracker) { base::CancelableTaskTracker* tracker) {
scoped_refptr<MostVisitedThreadSafe> sites = new MostVisitedThreadSafe(); tracker->PostTaskAndReplyWithResult(
tracker->PostTaskAndReply(
db_task_runner_.get(), FROM_HERE, db_task_runner_.get(), FROM_HERE,
base::BindOnce(&TopSitesBackend::GetMostVisitedSitesOnDBThread, this, base::BindOnce(&TopSitesBackend::GetMostVisitedSitesOnDBThread, this),
sites), std::move(callback));
base::BindOnce(std::move(callback), sites));
} }
void TopSitesBackend::UpdateTopSites(const TopSitesDelta& delta, void TopSitesBackend::UpdateTopSites(const TopSitesDelta& delta,
...@@ -85,13 +83,12 @@ void TopSitesBackend::ShutdownDBOnDBThread() { ...@@ -85,13 +83,12 @@ void TopSitesBackend::ShutdownDBOnDBThread() {
db_.reset(); db_.reset();
} }
void TopSitesBackend::GetMostVisitedSitesOnDBThread( MostVisitedURLList TopSitesBackend::GetMostVisitedSitesOnDBThread() {
scoped_refptr<MostVisitedThreadSafe> sites) {
DCHECK(db_task_runner_->RunsTasksInCurrentSequence()); DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
MostVisitedURLList list;
if (db_) { if (db_)
db_->GetSites(&(sites->data)); db_->GetSites(&list);
} return list;
} }
void TopSitesBackend::UpdateTopSitesOnDBThread( void TopSitesBackend::UpdateTopSitesOnDBThread(
......
...@@ -38,7 +38,7 @@ class TopSitesBackend : public base::RefCountedThreadSafe<TopSitesBackend> { ...@@ -38,7 +38,7 @@ class TopSitesBackend : public base::RefCountedThreadSafe<TopSitesBackend> {
}; };
using GetMostVisitedSitesCallback = using GetMostVisitedSitesCallback =
base::OnceCallback<void(const scoped_refptr<MostVisitedThreadSafe>&)>; base::OnceCallback<void(MostVisitedURLList)>;
TopSitesBackend(); TopSitesBackend();
...@@ -47,7 +47,7 @@ class TopSitesBackend : public base::RefCountedThreadSafe<TopSitesBackend> { ...@@ -47,7 +47,7 @@ class TopSitesBackend : public base::RefCountedThreadSafe<TopSitesBackend> {
// Schedules the db to be shutdown. // Schedules the db to be shutdown.
void Shutdown(); void Shutdown();
// Fetches MostVisitedThreadSafe. // Fetches MostVisitedURLList.
void GetMostVisitedSites(GetMostVisitedSitesCallback callback, void GetMostVisitedSites(GetMostVisitedSitesCallback callback,
base::CancelableTaskTracker* tracker); base::CancelableTaskTracker* tracker);
...@@ -70,8 +70,7 @@ class TopSitesBackend : public base::RefCountedThreadSafe<TopSitesBackend> { ...@@ -70,8 +70,7 @@ class TopSitesBackend : public base::RefCountedThreadSafe<TopSitesBackend> {
void ShutdownDBOnDBThread(); void ShutdownDBOnDBThread();
// Does the work of getting the most visited sites. // Does the work of getting the most visited sites.
void GetMostVisitedSitesOnDBThread( MostVisitedURLList GetMostVisitedSitesOnDBThread();
scoped_refptr<MostVisitedThreadSafe> sites);
// Updates top sites. // Updates top sites.
void UpdateTopSitesOnDBThread(const TopSitesDelta& delta, void UpdateTopSitesOnDBThread(const TopSitesDelta& delta,
......
...@@ -128,13 +128,11 @@ void TopSitesImpl::GetMostVisitedURLs( ...@@ -128,13 +128,11 @@ void TopSitesImpl::GetMostVisitedURLs(
callback.Run(filtered_urls); callback.Run(filtered_urls);
} }
// Returns the index of |url| in |urls|, or -1 if not found. static bool Contains(const MostVisitedURLList& urls, const GURL& url) {
static int IndexOf(const MostVisitedURLList& urls, const GURL& url) { return std::find_if(urls.begin(), urls.end(),
for (size_t i = 0; i < urls.size(); i++) { [&url](const MostVisitedURL& item) {
if (urls[i].url == url) return item.url == url;
return i; }) != urls.end();
}
return -1;
} }
void TopSitesImpl::SyncWithHistory() { void TopSitesImpl::SyncWithHistory() {
...@@ -232,7 +230,7 @@ void TopSitesImpl::RegisterPrefs(PrefRegistrySimple* registry) { ...@@ -232,7 +230,7 @@ void TopSitesImpl::RegisterPrefs(PrefRegistrySimple* registry) {
TopSitesImpl::~TopSitesImpl() = default; TopSitesImpl::~TopSitesImpl() = default;
void TopSitesImpl::StartQueryForMostVisited() { void TopSitesImpl::StartQueryForMostVisited() {
const int kDaysOfHistory = 90; constexpr int kDaysOfHistory = 90;
DCHECK(loaded_); DCHECK(loaded_);
timer_.Stop(); timer_.Stop();
...@@ -261,26 +259,19 @@ void TopSitesImpl::DiffMostVisited(const MostVisitedURLList& old_list, ...@@ -261,26 +259,19 @@ void TopSitesImpl::DiffMostVisited(const MostVisitedURLList& old_list,
// When we find a match in the old set, we'll reset its index to our special // When we find a match in the old set, we'll reset its index to our special
// marker. This allows us to quickly identify the deleted ones in a later // marker. This allows us to quickly identify the deleted ones in a later
// pass. // pass.
const size_t kAlreadyFoundMarker = static_cast<size_t>(-1); constexpr size_t kAlreadyFoundMarker = static_cast<size_t>(-1);
int rank = -1; int rank = -1;
for (size_t i = 0; i < new_list.size(); i++) { for (const auto& new_url : new_list) {
rank++; rank++;
auto found = all_old_urls.find(new_list[i].url); auto found = all_old_urls.find(new_url.url);
if (found == all_old_urls.end()) { if (found == all_old_urls.end()) {
MostVisitedURLWithRank added; delta->added.emplace_back(MostVisitedURLWithRank{new_url, rank});
added.url = new_list[i];
added.rank = rank;
delta->added.push_back(added);
} else { } else {
DCHECK(found->second != kAlreadyFoundMarker) DCHECK(found->second != kAlreadyFoundMarker)
<< "Same URL appears twice in the new list."; << "Same URL appears twice in the new list.";
int old_rank = found->second; int old_rank = found->second;
if (old_rank != rank) { if (old_rank != rank)
MostVisitedURLWithRank moved; delta->moved.emplace_back(MostVisitedURLWithRank{new_url, rank});
moved.url = new_list[i];
moved.rank = rank;
delta->moved.push_back(moved);
}
found->second = kAlreadyFoundMarker; found->second = kAlreadyFoundMarker;
} }
} }
...@@ -296,8 +287,9 @@ void TopSitesImpl::DiffMostVisited(const MostVisitedURLList& old_list, ...@@ -296,8 +287,9 @@ void TopSitesImpl::DiffMostVisited(const MostVisitedURLList& old_list,
bool TopSitesImpl::AddPrepopulatedPages(MostVisitedURLList* urls) const { bool TopSitesImpl::AddPrepopulatedPages(MostVisitedURLList* urls) const {
bool added = false; bool added = false;
for (const auto& prepopulated_page : prepopulated_pages_) { for (const auto& prepopulated_page : prepopulated_pages_) {
if (urls->size() < kTopSitesNumber && if (urls->size() >= kTopSitesNumber)
IndexOf(*urls, prepopulated_page.most_visited.url) == -1) { break;
if (!Contains(*urls, prepopulated_page.most_visited.url)) {
urls->push_back(prepopulated_page.most_visited); urls->push_back(prepopulated_page.most_visited);
added = true; added = true;
} }
...@@ -305,8 +297,8 @@ bool TopSitesImpl::AddPrepopulatedPages(MostVisitedURLList* urls) const { ...@@ -305,8 +297,8 @@ bool TopSitesImpl::AddPrepopulatedPages(MostVisitedURLList* urls) const {
return added; return added;
} }
void TopSitesImpl::ApplyBlacklist(const MostVisitedURLList& urls, MostVisitedURLList TopSitesImpl::ApplyBlacklist(
MostVisitedURLList* out) { const MostVisitedURLList& urls) {
// Log the number of times ApplyBlacklist is called so we can compute the // Log the number of times ApplyBlacklist is called so we can compute the
// average number of blacklisted items per user. // average number of blacklisted items per user.
const base::DictionaryValue* blacklist = const base::DictionaryValue* blacklist =
...@@ -314,15 +306,15 @@ void TopSitesImpl::ApplyBlacklist(const MostVisitedURLList& urls, ...@@ -314,15 +306,15 @@ void TopSitesImpl::ApplyBlacklist(const MostVisitedURLList& urls,
UMA_HISTOGRAM_BOOLEAN("TopSites.NumberOfApplyBlacklist", true); UMA_HISTOGRAM_BOOLEAN("TopSites.NumberOfApplyBlacklist", true);
UMA_HISTOGRAM_COUNTS_100("TopSites.NumberOfBlacklistedItems", UMA_HISTOGRAM_COUNTS_100("TopSites.NumberOfBlacklistedItems",
(blacklist ? blacklist->size() : 0)); (blacklist ? blacklist->size() : 0));
size_t num_urls = 0; MostVisitedURLList result;
for (size_t i = 0; i < urls.size(); ++i) { for (const auto& url : urls) {
if (!IsBlacklisted(urls[i].url)) { if (IsBlacklisted(url.url))
if (num_urls >= kTopSitesNumber) continue;
break; if (result.size() >= kTopSitesNumber)
num_urls++; break;
out->push_back(urls[i]); result.push_back(url);
}
} }
return result;
} }
// static // static
...@@ -332,11 +324,10 @@ std::string TopSitesImpl::GetURLHash(const GURL& url) { ...@@ -332,11 +324,10 @@ std::string TopSitesImpl::GetURLHash(const GURL& url) {
return base::MD5String(url.spec()); return base::MD5String(url.spec());
} }
void TopSitesImpl::SetTopSites(const MostVisitedURLList& new_top_sites, void TopSitesImpl::SetTopSites(MostVisitedURLList top_sites,
const CallLocation location) { const CallLocation location) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
MostVisitedURLList top_sites(new_top_sites);
AddPrepopulatedPages(&top_sites); AddPrepopulatedPages(&top_sites);
TopSitesDelta delta; TopSitesDelta delta;
...@@ -373,7 +364,7 @@ void TopSitesImpl::SetTopSites(const MostVisitedURLList& new_top_sites, ...@@ -373,7 +364,7 @@ void TopSitesImpl::SetTopSites(const MostVisitedURLList& new_top_sites,
// We always do the following steps (setting top sites in cache, and resetting // We always do the following steps (setting top sites in cache, and resetting
// thread safe cache ...) as this method is invoked during startup at which // thread safe cache ...) as this method is invoked during startup at which
// point the caches haven't been updated yet. // point the caches haven't been updated yet.
top_sites_ = top_sites; top_sites_ = std::move(top_sites);
ResetThreadSafeCache(); ResetThreadSafeCache();
...@@ -409,8 +400,8 @@ void TopSitesImpl::MoveStateToLoaded() { ...@@ -409,8 +400,8 @@ void TopSitesImpl::MoveStateToLoaded() {
} }
} }
for (size_t i = 0; i < pending_callbacks.size(); i++) for (auto& callback : pending_callbacks)
pending_callbacks[i].Run(urls); callback.Run(urls);
if (history_service_) if (history_service_)
history_service_observer_.Add(history_service_); history_service_observer_.Add(history_service_);
...@@ -420,9 +411,7 @@ void TopSitesImpl::MoveStateToLoaded() { ...@@ -420,9 +411,7 @@ void TopSitesImpl::MoveStateToLoaded() {
void TopSitesImpl::ResetThreadSafeCache() { void TopSitesImpl::ResetThreadSafeCache() {
base::AutoLock lock(lock_); base::AutoLock lock(lock_);
MostVisitedURLList filtered; thread_safe_cache_ = ApplyBlacklist(top_sites_);
ApplyBlacklist(top_sites_, &filtered);
thread_safe_cache_ = filtered;
} }
void TopSitesImpl::ScheduleUpdateTimer() { void TopSitesImpl::ScheduleUpdateTimer() {
...@@ -433,13 +422,12 @@ void TopSitesImpl::ScheduleUpdateTimer() { ...@@ -433,13 +422,12 @@ void TopSitesImpl::ScheduleUpdateTimer() {
&TopSitesImpl::StartQueryForMostVisited); &TopSitesImpl::StartQueryForMostVisited);
} }
void TopSitesImpl::OnGotMostVisitedURLs( void TopSitesImpl::OnGotMostVisitedURLs(MostVisitedURLList sites) {
const scoped_refptr<MostVisitedThreadSafe>& sites) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
// Set |top_sites_| directly so that SetTopSites() diffs correctly. // Set |top_sites_| directly so that SetTopSites() diffs correctly.
top_sites_ = sites->data; top_sites_ = sites;
SetTopSites(sites->data, CALL_LOCATION_FROM_ON_GOT_MOST_VISITED_URLS); SetTopSites(std::move(sites), CALL_LOCATION_FROM_ON_GOT_MOST_VISITED_URLS);
MoveStateToLoaded(); MoveStateToLoaded();
...@@ -449,7 +437,7 @@ void TopSitesImpl::OnGotMostVisitedURLs( ...@@ -449,7 +437,7 @@ void TopSitesImpl::OnGotMostVisitedURLs(
} }
void TopSitesImpl::OnTopSitesAvailableFromHistory(MostVisitedURLList pages) { void TopSitesImpl::OnTopSitesAvailableFromHistory(MostVisitedURLList pages) {
SetTopSites(pages, CALL_LOCATION_FROM_OTHER_PLACES); SetTopSites(std::move(pages), CALL_LOCATION_FROM_OTHER_PLACES);
} }
void TopSitesImpl::OnURLsDeleted(HistoryService* history_service, void TopSitesImpl::OnURLsDeleted(HistoryService* history_service,
......
...@@ -125,7 +125,7 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver { ...@@ -125,7 +125,7 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver {
// Takes |urls|, produces it's copy in |out| after removing blacklisted URLs. // Takes |urls|, produces it's copy in |out| after removing blacklisted URLs.
// Also ensures we respect the maximum number TopSites URLs. // Also ensures we respect the maximum number TopSites URLs.
void ApplyBlacklist(const MostVisitedURLList& urls, MostVisitedURLList* out); MostVisitedURLList ApplyBlacklist(const MostVisitedURLList& urls);
// Returns an MD5 hash of the URL. Hashing is required for blacklisted URLs. // Returns an MD5 hash of the URL. Hashing is required for blacklisted URLs.
static std::string GetURLHash(const GURL& url); static std::string GetURLHash(const GURL& url);
...@@ -133,7 +133,7 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver { ...@@ -133,7 +133,7 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver {
// Updates URLs in |cache_| and the db (in the background). The URLs in // Updates URLs in |cache_| and the db (in the background). The URLs in
// |new_top_sites| replace those in |cache_|. All mutations to cache_ *must* // |new_top_sites| replace those in |cache_|. All mutations to cache_ *must*
// go through this. Should be called from the UI thread. // go through this. Should be called from the UI thread.
void SetTopSites(const MostVisitedURLList& new_top_sites, void SetTopSites(MostVisitedURLList new_top_sites,
const CallLocation location); const CallLocation location);
// Returns the number of most visited results to request from history. This // Returns the number of most visited results to request from history. This
...@@ -153,7 +153,7 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver { ...@@ -153,7 +153,7 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver {
// Callback from TopSites with the list of top sites. Should be called from // Callback from TopSites with the list of top sites. Should be called from
// the UI thread. // the UI thread.
void OnGotMostVisitedURLs(const scoped_refptr<MostVisitedThreadSafe>& sites); void OnGotMostVisitedURLs(MostVisitedURLList sites);
// Called when history service returns a list of top URLs. // Called when history service returns a list of top URLs.
void OnTopSitesAvailableFromHistory(MostVisitedURLList data); void OnTopSitesAvailableFromHistory(MostVisitedURLList data);
...@@ -188,7 +188,7 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver { ...@@ -188,7 +188,7 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver {
// The pending requests for the top sites list. Can only be non-empty at // The pending requests for the top sites list. Can only be non-empty at
// startup. After we read the top sites from the DB, we'll always have a // startup. After we read the top sites from the DB, we'll always have a
// cached list and be able to run callbacks immediately. // cached list and be able to run callbacks immediately.
PendingCallbacks pending_callbacks_; PendingCallbacks pending_callbacks_ GUARDED_BY(lock_);
// URL List of prepopulated page. // URL List of prepopulated page.
const PrepopulatedPageList prepopulated_pages_; const PrepopulatedPageList prepopulated_pages_;
......
...@@ -203,7 +203,7 @@ class TopSitesImplTest : public HistoryUnitTestBase { ...@@ -203,7 +203,7 @@ class TopSitesImplTest : public HistoryUnitTestBase {
// Wrappers that allow private TopSites functions to be called from the // Wrappers that allow private TopSites functions to be called from the
// individual tests without making them all be friends. // individual tests without making them all be friends.
void SetTopSites(const MostVisitedURLList& new_top_sites) { void SetTopSites(const MostVisitedURLList& new_top_sites) {
top_sites()->SetTopSites(new_top_sites, top_sites()->SetTopSites(MostVisitedURLList(new_top_sites),
TopSitesImpl::CALL_LOCATION_FROM_OTHER_PLACES); TopSitesImpl::CALL_LOCATION_FROM_OTHER_PLACES);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment