121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <algorithm> 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_path.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_util.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/perftimer.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/shared_memory.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/test/test_file_util.h" 1521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/visitedlink/visitedlink_master.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "testing/gtest/include/gtest/gtest.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeDelta; 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// how we generate URLs, note that the two strings should be the same length 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int add_count = 10000; 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int load_test_add_count = 250000; 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char added_prefix[] = "http://www.google.com/stuff/something/foo?session=85025602345625&id=1345142319023&seq="; 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char unadded_prefix[] = "http://www.google.org/stuff/something/foo?session=39586739476365&id=2347624314402&seq="; 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns a URL with the given prefix and index 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGURL TestURL(const char* prefix, int i) { 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return GURL(StringPrintf("%s%d", prefix, i)); 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// We have no slaves, so all methods on this listener are a no-ops. 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass DummyVisitedLinkEventListener : public VisitedLinkMaster::Listener { 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DummyVisitedLinkEventListener() {} 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void NewTable(base::SharedMemory* table) {} 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void Add(VisitedLinkCommon::Fingerprint) {} 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void Reset() {} 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static DummyVisitedLinkEventListener* GetInstance() { 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static DummyVisitedLinkEventListener instance; 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return &instance; 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// this checks IsVisited for the URLs starting with the given prefix and 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// within the given range 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CheckVisited(VisitedLinkMaster& master, const char* prefix, 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int begin, int end) { 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = begin; i < end; i++) 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch master.IsVisited(TestURL(prefix, i)); 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Fills that master's table with URLs starting with the given prefix and 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// within the given range 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FillTable(VisitedLinkMaster& master, const char* prefix, 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int begin, int end) { 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = begin; i < end; i++) 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch master.AddURL(TestURL(prefix, i)); 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass VisitedLink : public testing::Test { 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected: 6672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FilePath db_path_; 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void SetUp() { 6872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ASSERT_TRUE(file_util::CreateTemporaryFile(&db_path_)); 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void TearDown() { 7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen file_util::Delete(db_path_, false); 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This test tests adding many things to a database, and how long it takes 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// to query the database with different numbers of things in it. The time 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// is the total time to do all the operations, and as such, it is only 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// useful for a regression test. If there is a regression, it might be 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// useful to make another set of tests to test these things in isolation. 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(VisitedLink, TestAddAndQuery) { 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // init 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitedLinkMaster master(DummyVisitedLinkEventListener::GetInstance(), 8572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NULL, true, db_path_, 0); 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(master.Init()); 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PerfTimeLogger timer("Visited_link_add_and_query"); 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // first check without anything in the table 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CheckVisited(master, added_prefix, 0, add_count); 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // now fill half the table 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int half_size = add_count / 2; 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FillTable(master, added_prefix, 0, half_size); 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // check the table again, half of these URLs will be visited, the other half 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // will not 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CheckVisited(master, added_prefix, 0, add_count); 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // fill the rest of the table 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FillTable(master, added_prefix, half_size, add_count); 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // check URLs, doing half visited, half unvisited 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CheckVisited(master, added_prefix, 0, add_count); 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CheckVisited(master, unadded_prefix, 0, add_count); 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tests how long it takes to write and read a large database to and from disk. 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(VisitedLink, TestLoad) { 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // create a big DB 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PerfTimeLogger table_initialization_timer("Table_initialization"); 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitedLinkMaster master(DummyVisitedLinkEventListener::GetInstance(), 11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NULL, true, db_path_, 0); 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // time init with empty table 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PerfTimeLogger initTimer("Empty_visited_link_init"); 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool success = master.Init(); 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch initTimer.Done(); 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(success); 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // add a bunch of stuff 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(maruel): This is very inefficient because the file gets rewritten 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // many time and this is the actual bottleneck of this test. The file should 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // only get written that the end of the FillTable call, not 4169(!) times. 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FillTable(master, added_prefix, 0, load_test_add_count); 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // time writing the file out out 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PerfTimeLogger flushTimer("Visited_link_database_flush"); 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch master.RewriteFile(); 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(maruel): Without calling FlushFileBuffers(master.file_); you don't 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // know really how much time it took to write the file. 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch flushTimer.Done(); 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch table_initialization_timer.Done(); 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // test loading the DB back, we do this several times since the flushing is 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // not very reliable. 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int load_count = 5; 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<double> cold_load_times; 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<double> hot_load_times; 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < load_count; i++) { 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // make sure the file has to be re-loaded 14772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen file_util::EvictFileFromSystemCache(db_path_); 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // cold load (no OS cache, hopefully) 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PerfTimer cold_timer; 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitedLinkMaster master(DummyVisitedLinkEventListener::GetInstance(), 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NULL, 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch true, 15672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen db_path_, 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0); 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool success = master.Init(); 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeDelta elapsed = cold_timer.Elapsed(); 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(success); 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cold_load_times.push_back(elapsed.InMillisecondsF()); 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // hot load (with OS caching the file in memory) 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PerfTimer hot_timer; 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitedLinkMaster master(DummyVisitedLinkEventListener::GetInstance(), 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NULL, 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch true, 17272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen db_path_, 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0); 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool success = master.Init(); 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeDelta elapsed = hot_timer.Elapsed(); 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(success); 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hot_load_times.push_back(elapsed.InMillisecondsF()); 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We discard the max and return the average time. 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cold_load_times.erase(std::max_element(cold_load_times.begin(), 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cold_load_times.end())); 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hot_load_times.erase(std::max_element(hot_load_times.begin(), 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hot_load_times.end())); 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch double cold_sum = 0, hot_sum = 0; 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < static_cast<int>(cold_load_times.size()); i++) { 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cold_sum += cold_load_times[i]; 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hot_sum += hot_load_times[i]; 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogPerfResult("Visited_link_cold_load_time", 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cold_sum / cold_load_times.size(), "ms"); 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogPerfResult("Visited_link_hot_load_time", 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hot_sum / hot_load_times.size(), "ms"); 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 198