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