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
3 // found in the LICENSE file.
9 #include "base/files/file_path.h"
10 #include "base/files/file_util.h"
11 #include "base/memory/shared_memory.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/test/perf_log.h"
14 #include "base/test/perf_time_logger.h"
15 #include "base/test/test_file_util.h"
16 #include "base/timer/elapsed_timer.h"
17 #include "components/visitedlink/browser/visitedlink_master.h"
18 #include "testing/gtest/include/gtest/gtest.h"
21 using base::TimeDelta
;
23 namespace visitedlink
{
27 // how we generate URLs, note that the two strings should be the same length
28 const int add_count
= 10000;
29 const int load_test_add_count
= 250000;
30 const char added_prefix
[] = "http://www.google.com/stuff/something/foo?session=85025602345625&id=1345142319023&seq=";
31 const char unadded_prefix
[] = "http://www.google.org/stuff/something/foo?session=39586739476365&id=2347624314402&seq=";
33 // Returns a URL with the given prefix and index
34 GURL
TestURL(const char* prefix
, int i
) {
35 return GURL(base::StringPrintf("%s%d", prefix
, i
));
38 // We have no slaves, so all methods on this listener are a no-ops.
39 class DummyVisitedLinkEventListener
: public VisitedLinkMaster::Listener
{
41 DummyVisitedLinkEventListener() {}
42 void NewTable(base::SharedMemory
* table
) override
{}
43 void Add(VisitedLinkCommon::Fingerprint
) override
{}
44 void Reset() override
{}
48 // this checks IsVisited for the URLs starting with the given prefix and
49 // within the given range
50 void CheckVisited(VisitedLinkMaster
& master
, const char* prefix
,
52 for (int i
= begin
; i
< end
; i
++)
53 master
.IsVisited(TestURL(prefix
, i
));
56 // Fills that master's table with URLs starting with the given prefix and
57 // within the given range
58 void FillTable(VisitedLinkMaster
& master
, const char* prefix
,
60 for (int i
= begin
; i
< end
; i
++)
61 master
.AddURL(TestURL(prefix
, i
));
64 class VisitedLink
: public testing::Test
{
66 base::FilePath db_path_
;
67 void SetUp() override
{ ASSERT_TRUE(base::CreateTemporaryFile(&db_path_
)); }
68 void TearDown() override
{ base::DeleteFile(db_path_
, false); }
73 // This test tests adding many things to a database, and how long it takes
74 // to query the database with different numbers of things in it. The time
75 // is the total time to do all the operations, and as such, it is only
76 // useful for a regression test. If there is a regression, it might be
77 // useful to make another set of tests to test these things in isolation.
78 TEST_F(VisitedLink
, TestAddAndQuery
) {
80 VisitedLinkMaster
master(new DummyVisitedLinkEventListener(),
81 NULL
, true, true, db_path_
, 0);
82 ASSERT_TRUE(master
.Init());
84 base::PerfTimeLogger
timer("Visited_link_add_and_query");
86 // first check without anything in the table
87 CheckVisited(master
, added_prefix
, 0, add_count
);
89 // now fill half the table
90 const int half_size
= add_count
/ 2;
91 FillTable(master
, added_prefix
, 0, half_size
);
93 // check the table again, half of these URLs will be visited, the other half
95 CheckVisited(master
, added_prefix
, 0, add_count
);
97 // fill the rest of the table
98 FillTable(master
, added_prefix
, half_size
, add_count
);
100 // check URLs, doing half visited, half unvisited
101 CheckVisited(master
, added_prefix
, 0, add_count
);
102 CheckVisited(master
, unadded_prefix
, 0, add_count
);
105 // Tests how long it takes to write and read a large database to and from disk.
106 TEST_F(VisitedLink
, TestLoad
) {
109 base::PerfTimeLogger
table_initialization_timer("Table_initialization");
111 VisitedLinkMaster
master(new DummyVisitedLinkEventListener(),
112 NULL
, true, true, db_path_
, 0);
114 // time init with empty table
115 base::PerfTimeLogger
initTimer("Empty_visited_link_init");
116 bool success
= master
.Init();
118 ASSERT_TRUE(success
);
120 // add a bunch of stuff
121 // TODO(maruel): This is very inefficient because the file gets rewritten
122 // many time and this is the actual bottleneck of this test. The file should
123 // only get written that the end of the FillTable call, not 4169(!) times.
124 FillTable(master
, added_prefix
, 0, load_test_add_count
);
126 // time writing the file out out
127 base::PerfTimeLogger
flushTimer("Visited_link_database_flush");
128 master
.RewriteFile();
129 // TODO(maruel): Without calling FlushFileBuffers(master.file_); you don't
130 // know really how much time it took to write the file.
133 table_initialization_timer
.Done();
136 // test loading the DB back, we do this several times since the flushing is
137 // not very reliable.
138 const int load_count
= 5;
139 std::vector
<double> cold_load_times
;
140 std::vector
<double> hot_load_times
;
141 for (int i
= 0; i
< load_count
; i
++) {
142 // make sure the file has to be re-loaded
143 base::EvictFileFromSystemCache(db_path_
);
145 // cold load (no OS cache, hopefully)
147 base::ElapsedTimer cold_timer
;
149 VisitedLinkMaster
master(new DummyVisitedLinkEventListener(),
155 bool success
= master
.Init();
156 TimeDelta elapsed
= cold_timer
.Elapsed();
157 ASSERT_TRUE(success
);
159 cold_load_times
.push_back(elapsed
.InMillisecondsF());
162 // hot load (with OS caching the file in memory)
164 base::ElapsedTimer hot_timer
;
166 VisitedLinkMaster
master(new DummyVisitedLinkEventListener(),
172 bool success
= master
.Init();
173 TimeDelta elapsed
= hot_timer
.Elapsed();
174 ASSERT_TRUE(success
);
176 hot_load_times
.push_back(elapsed
.InMillisecondsF());
180 // We discard the max and return the average time.
181 cold_load_times
.erase(std::max_element(cold_load_times
.begin(),
182 cold_load_times
.end()));
183 hot_load_times
.erase(std::max_element(hot_load_times
.begin(),
184 hot_load_times
.end()));
186 double cold_sum
= 0, hot_sum
= 0;
187 for (int i
= 0; i
< static_cast<int>(cold_load_times
.size()); i
++) {
188 cold_sum
+= cold_load_times
[i
];
189 hot_sum
+= hot_load_times
[i
];
192 "Visited_link_cold_load_time", cold_sum
/ cold_load_times
.size(), "ms");
194 "Visited_link_hot_load_time", hot_sum
/ hot_load_times
.size(), "ms");
197 } // namespace visitedlink