Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(448)

Side by Side Diff: net/disk_cache/disk_cache_perftest.cc

Issue 1976453003: Add headers-only component to DiskCachePerfTest. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@open-speeder-2
Patch Set: block fixes Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <string> 5 #include <string>
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/files/file_enumerator.h" 9 #include "base/files/file_enumerator.h"
10 #include "base/files/file_path.h" 10 #include "base/files/file_path.h"
(...skipping 11 matching lines...) Expand all
22 #include "net/disk_cache/disk_cache.h" 22 #include "net/disk_cache/disk_cache.h"
23 #include "net/disk_cache/disk_cache_test_base.h" 23 #include "net/disk_cache/disk_cache_test_base.h"
24 #include "net/disk_cache/disk_cache_test_util.h" 24 #include "net/disk_cache/disk_cache_test_util.h"
25 #include "testing/gtest/include/gtest/gtest.h" 25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "testing/platform_test.h" 26 #include "testing/platform_test.h"
27 27
28 using base::Time; 28 using base::Time;
29 29
30 namespace { 30 namespace {
31 31
32 class DiskCachePerfTest : public DiskCacheTestWithCache {
33 protected:
34 void CacheBackendPerformance();
35 };
36
37 struct TestEntry { 32 struct TestEntry {
38 std::string key; 33 std::string key;
39 int data_len; 34 int data_len;
40 }; 35 };
41 typedef std::vector<TestEntry> TestEntries;
42 36
43 const int kMaxSize = 16 * 1024 - 1; 37 class DiskCachePerfTest : public DiskCacheTestWithCache {
38 protected:
39 enum class WhatToRead {
40 HEADERS_ONLY,
41 HEADERS_AND_BODY,
42 };
43
44 // Helper methods for constructing tests.
45 bool TimeWrite();
46 bool TimeRead(WhatToRead what_to_read, const char* timer_message);
47 void ResetAndEvictSystemDiskCache();
48
49 // Complete perf tests.
50 void CacheBackendPerformance();
51
52 const int kNumEntries = 1000;
53 const int kHeadersSize = 200;
54 const int kBodySize = 16 * 1024 - 1;
55
56 std::vector<TestEntry> entries_;
57 };
44 58
45 // Creates num_entries on the cache, and writes 200 bytes of metadata and up 59 // Creates num_entries on the cache, and writes 200 bytes of metadata and up
46 // to kMaxSize of data to each entry. 60 // to kBodySize of data to each entry.
47 bool TimeWrite(int num_entries, 61 bool DiskCachePerfTest::TimeWrite() {
48 disk_cache::Backend* cache, 62 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kHeadersSize));
49 TestEntries* entries) { 63 scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kBodySize));
50 const int kSize1 = 200;
51 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1));
52 scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kMaxSize));
53 64
54 CacheTestFillBuffer(buffer1->data(), kSize1, false); 65 CacheTestFillBuffer(buffer1->data(), kHeadersSize, false);
55 CacheTestFillBuffer(buffer2->data(), kMaxSize, false); 66 CacheTestFillBuffer(buffer2->data(), kBodySize, false);
56 67
57 int expected = 0; 68 int expected = 0;
58 69
59 MessageLoopHelper helper; 70 MessageLoopHelper helper;
60 CallbackTest callback(&helper, true); 71 CallbackTest callback(&helper, true);
61 72
62 base::PerfTimeLogger timer("Write disk cache entries"); 73 base::PerfTimeLogger timer("Write disk cache entries");
63 74
64 for (int i = 0; i < num_entries; i++) { 75 for (int i = 0; i < kNumEntries; i++) {
65 TestEntry entry; 76 TestEntry entry;
66 entry.key = GenerateKey(true); 77 entry.key = GenerateKey(true);
67 entry.data_len = rand() % kMaxSize; 78 entry.data_len = rand() % kBodySize;
68 entries->push_back(entry); 79 entries_.push_back(entry);
69 80
70 disk_cache::Entry* cache_entry; 81 disk_cache::Entry* cache_entry;
71 net::TestCompletionCallback cb; 82 net::TestCompletionCallback cb;
72 int rv = cache->CreateEntry(entry.key, &cache_entry, cb.callback()); 83 int rv = cache_->CreateEntry(entry.key, &cache_entry, cb.callback());
73 if (net::OK != cb.GetResult(rv)) 84 if (net::OK != cb.GetResult(rv))
74 break; 85 break;
75 int ret = cache_entry->WriteData( 86 int ret = cache_entry->WriteData(
76 0, 0, buffer1.get(), kSize1, 87 0, 0, buffer1.get(), kHeadersSize,
77 base::Bind(&CallbackTest::Run, base::Unretained(&callback)), false); 88 base::Bind(&CallbackTest::Run, base::Unretained(&callback)), false);
78 if (net::ERR_IO_PENDING == ret) 89 if (net::ERR_IO_PENDING == ret)
79 expected++; 90 expected++;
80 else if (kSize1 != ret) 91 else if (kHeadersSize != ret)
81 break; 92 break;
82 93
83 ret = cache_entry->WriteData( 94 ret = cache_entry->WriteData(
84 1, 0, buffer2.get(), entry.data_len, 95 1, 0, buffer2.get(), entry.data_len,
85 base::Bind(&CallbackTest::Run, base::Unretained(&callback)), false); 96 base::Bind(&CallbackTest::Run, base::Unretained(&callback)), false);
86 if (net::ERR_IO_PENDING == ret) 97 if (net::ERR_IO_PENDING == ret)
87 expected++; 98 expected++;
88 else if (entry.data_len != ret) 99 else if (entry.data_len != ret)
89 break; 100 break;
90 cache_entry->Close(); 101 cache_entry->Close();
91 } 102 }
92 103
93 helper.WaitUntilCacheIoFinished(expected); 104 helper.WaitUntilCacheIoFinished(expected);
94 timer.Done(); 105 timer.Done();
95 106
96 return (expected == helper.callbacks_called()); 107 return expected == helper.callbacks_called();
97 } 108 }
98 109
99 // Reads the data and metadata from each entry listed on |entries|. 110 // Reads the data and metadata from each entry listed on |entries|.
100 bool TimeRead(int num_entries, 111 bool DiskCachePerfTest::TimeRead(WhatToRead what_to_read,
101 disk_cache::Backend* cache, 112 const char* timer_message) {
102 const TestEntries& entries, 113 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kHeadersSize));
103 bool cold) { 114 scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kBodySize));
104 const int kSize1 = 200;
105 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize1));
106 scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kMaxSize));
107 115
108 CacheTestFillBuffer(buffer1->data(), kSize1, false); 116 CacheTestFillBuffer(buffer1->data(), kHeadersSize, false);
109 CacheTestFillBuffer(buffer2->data(), kMaxSize, false); 117 CacheTestFillBuffer(buffer2->data(), kBodySize, false);
110 118
111 int expected = 0; 119 int expected = 0;
112 120
113 MessageLoopHelper helper; 121 MessageLoopHelper helper;
114 CallbackTest callback(&helper, true); 122 CallbackTest callback(&helper, true);
115 123
116 const char* message = cold ? "Read disk cache entries (cold)" 124 base::PerfTimeLogger timer(timer_message);
117 : "Read disk cache entries (warm)";
118 base::PerfTimeLogger timer(message);
119 125
120 for (int i = 0; i < num_entries; i++) { 126 for (int i = 0; i < kNumEntries; i++) {
121 disk_cache::Entry* cache_entry; 127 disk_cache::Entry* cache_entry;
122 net::TestCompletionCallback cb; 128 net::TestCompletionCallback cb;
123 int rv = cache->OpenEntry(entries[i].key, &cache_entry, cb.callback()); 129 int rv = cache_->OpenEntry(entries_[i].key, &cache_entry, cb.callback());
124 if (net::OK != cb.GetResult(rv)) 130 if (net::OK != cb.GetResult(rv))
125 break; 131 break;
126 int ret = cache_entry->ReadData( 132 int ret = cache_entry->ReadData(
127 0, 0, buffer1.get(), kSize1, 133 0, 0, buffer1.get(), kHeadersSize,
128 base::Bind(&CallbackTest::Run, base::Unretained(&callback))); 134 base::Bind(&CallbackTest::Run, base::Unretained(&callback)));
129 if (net::ERR_IO_PENDING == ret) 135 if (net::ERR_IO_PENDING == ret)
130 expected++; 136 expected++;
131 else if (kSize1 != ret) 137 else if (kHeadersSize != ret)
132 break; 138 break;
133 139
134 ret = cache_entry->ReadData( 140 if (what_to_read == WhatToRead::HEADERS_AND_BODY) {
135 1, 0, buffer2.get(), entries[i].data_len, 141 ret = cache_entry->ReadData(
136 base::Bind(&CallbackTest::Run, base::Unretained(&callback))); 142 1, 0, buffer2.get(), entries_[i].data_len,
137 if (net::ERR_IO_PENDING == ret) 143 base::Bind(&CallbackTest::Run, base::Unretained(&callback)));
138 expected++; 144 if (net::ERR_IO_PENDING == ret)
139 else if (entries[i].data_len != ret) 145 expected++;
140 break; 146 else if (entries_[i].data_len != ret)
147 break;
148 }
149
141 cache_entry->Close(); 150 cache_entry->Close();
142 } 151 }
143 152
144 helper.WaitUntilCacheIoFinished(expected); 153 helper.WaitUntilCacheIoFinished(expected);
145 timer.Done(); 154 timer.Done();
146 155
147 return (expected == helper.callbacks_called()); 156 return (expected == helper.callbacks_called());
148 } 157 }
149 158
150 int BlockSize() {
151 // We can use form 1 to 4 blocks.
152 return (rand() & 0x3) + 1;
153 }
154
155 TEST_F(DiskCachePerfTest, BlockfileHashes) { 159 TEST_F(DiskCachePerfTest, BlockfileHashes) {
156 int seed = static_cast<int>(Time::Now().ToInternalValue()); 160 int seed = static_cast<int>(Time::Now().ToInternalValue());
157 srand(seed); 161 srand(seed);
158 162
159 base::PerfTimeLogger timer("Hash disk cache keys"); 163 base::PerfTimeLogger timer("Hash disk cache keys");
160 for (int i = 0; i < 300000; i++) { 164 for (int i = 0; i < 300000; i++) {
161 std::string key = GenerateKey(true); 165 std::string key = GenerateKey(true);
162 base::Hash(key); 166 base::Hash(key);
163 } 167 }
164 timer.Done(); 168 timer.Done();
165 } 169 }
166 170
167 void DiskCachePerfTest::CacheBackendPerformance() { 171 void DiskCachePerfTest::ResetAndEvictSystemDiskCache() {
168 base::Thread cache_thread("CacheThread");
169 ASSERT_TRUE(cache_thread.StartWithOptions(
170 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
171
172 int seed = static_cast<int>(Time::Now().ToInternalValue());
173 srand(seed);
174
175 InitCache();
176
177 TestEntries entries;
178 int num_entries = 1000;
179
180 EXPECT_TRUE(TimeWrite(num_entries, cache_.get(), &entries));
181
182 base::MessageLoop::current()->RunUntilIdle(); 172 base::MessageLoop::current()->RunUntilIdle();
183 cache_.reset(); 173 cache_.reset();
184 174
185 // Flush all files in the cache out of system memory. 175 // Flush all files in the cache out of system memory.
186 const base::FilePath::StringType file_pattern = FILE_PATH_LITERAL("*"); 176 const base::FilePath::StringType file_pattern = FILE_PATH_LITERAL("*");
187 base::FileEnumerator enumerator(cache_path_, true /* recursive */, 177 base::FileEnumerator enumerator(cache_path_, true /* recursive */,
188 base::FileEnumerator::FILES, file_pattern); 178 base::FileEnumerator::FILES, file_pattern);
189 for (base::FilePath file_path = enumerator.Next(); !file_path.empty(); 179 for (base::FilePath file_path = enumerator.Next(); !file_path.empty();
190 file_path = enumerator.Next()) { 180 file_path = enumerator.Next()) {
191 ASSERT_TRUE(base::EvictFileFromSystemCache(file_path)); 181 ASSERT_TRUE(base::EvictFileFromSystemCache(file_path));
192 } 182 }
193 // And, cache directories. 183 // And, cache directories.
194 if (simple_cache_mode_) { 184 if (simple_cache_mode_) {
195 ASSERT_TRUE( 185 ASSERT_TRUE(
196 base::EvictFileFromSystemCache(cache_path_.AppendASCII("index-dir"))); 186 base::EvictFileFromSystemCache(cache_path_.AppendASCII("index-dir")));
197 } 187 }
198 ASSERT_TRUE(base::EvictFileFromSystemCache(cache_path_)); 188 ASSERT_TRUE(base::EvictFileFromSystemCache(cache_path_));
199 189
200 DisableFirstCleanup(); 190 DisableFirstCleanup();
201 InitCache(); 191 InitCache();
192 }
202 193
203 EXPECT_TRUE(TimeRead(num_entries, cache_.get(), entries, true)); 194 void DiskCachePerfTest::CacheBackendPerformance() {
204 EXPECT_TRUE(TimeRead(num_entries, cache_.get(), entries, false)); 195 InitCache();
196 EXPECT_TRUE(TimeWrite());
197
198 ResetAndEvictSystemDiskCache();
199 EXPECT_TRUE(TimeRead(WhatToRead::HEADERS_ONLY,
200 "Read disk cache headers only (cold)"));
201 EXPECT_TRUE(TimeRead(WhatToRead::HEADERS_ONLY,
202 "Read disk cache headers only (warm)"));
203 base::MessageLoop::current()->RunUntilIdle();
204
205 ResetAndEvictSystemDiskCache();
206 EXPECT_TRUE(
207 TimeRead(WhatToRead::HEADERS_AND_BODY, "Read disk cache entries (cold)"));
208 EXPECT_TRUE(
209 TimeRead(WhatToRead::HEADERS_AND_BODY, "Read disk cache entries (warm)"));
205 base::MessageLoop::current()->RunUntilIdle(); 210 base::MessageLoop::current()->RunUntilIdle();
206 } 211 }
207 212
208 TEST_F(DiskCachePerfTest, CacheBackendPerformance) { 213 TEST_F(DiskCachePerfTest, CacheBackendPerformance) {
209 CacheBackendPerformance(); 214 CacheBackendPerformance();
210 } 215 }
211 216
212 TEST_F(DiskCachePerfTest, SimpleCacheBackendPerformance) { 217 TEST_F(DiskCachePerfTest, SimpleCacheBackendPerformance) {
213 SetSimpleCacheMode(); 218 SetSimpleCacheMode();
214 CacheBackendPerformance(); 219 CacheBackendPerformance();
215 } 220 }
216 221
222 int BlockSize() {
223 // We can use form 1 to 4 blocks.
224 return (rand() & 0x3) + 1;
225 }
226
217 // Creating and deleting "entries" on a block-file is something quite frequent 227 // Creating and deleting "entries" on a block-file is something quite frequent
218 // (after all, almost everything is stored on block files). The operation is 228 // (after all, almost everything is stored on block files). The operation is
219 // almost free when the file is empty, but can be expensive if the file gets 229 // almost free when the file is empty, but can be expensive if the file gets
220 // fragmented, or if we have multiple files. This test measures that scenario, 230 // fragmented, or if we have multiple files. This test measures that scenario,
221 // by using multiple, highly fragmented files. 231 // by using multiple, highly fragmented files.
222 TEST_F(DiskCachePerfTest, BlockFilesPerformance) { 232 TEST_F(DiskCachePerfTest, BlockFilesPerformance) {
223 ASSERT_TRUE(CleanupCacheDir()); 233 ASSERT_TRUE(CleanupCacheDir());
224 234
225 disk_cache::BlockFiles files(cache_path_); 235 disk_cache::BlockFiles files(cache_path_);
226 ASSERT_TRUE(files.Init(true)); 236 ASSERT_TRUE(files.Init(true));
227 237
228 int seed = static_cast<int>(Time::Now().ToInternalValue()); 238 int seed = static_cast<int>(Time::Now().ToInternalValue());
229 srand(seed); 239 srand(seed);
230 240
231 const int kNumEntries = 60000; 241 const int kNumBlocks = 60000;
232 disk_cache::Addr* address = new disk_cache::Addr[kNumEntries]; 242 disk_cache::Addr address[kNumBlocks];
233 243
234 base::PerfTimeLogger timer1("Fill three block-files"); 244 base::PerfTimeLogger timer1("Fill three block-files");
235 245
236 // Fill up the 32-byte block file (use three files). 246 // Fill up the 32-byte block file (use three files).
237 for (int i = 0; i < kNumEntries; i++) { 247 for (int i = 0; i < kNumBlocks; i++) {
238 EXPECT_TRUE( 248 EXPECT_TRUE(
239 files.CreateBlock(disk_cache::RANKINGS, BlockSize(), &address[i])); 249 files.CreateBlock(disk_cache::RANKINGS, BlockSize(), &address[i]));
240 } 250 }
241 251
242 timer1.Done(); 252 timer1.Done();
243 base::PerfTimeLogger timer2("Create and delete blocks"); 253 base::PerfTimeLogger timer2("Create and delete blocks");
244 254
245 for (int i = 0; i < 200000; i++) { 255 for (int i = 0; i < 200000; i++) {
246 int entry = rand() * (kNumEntries / RAND_MAX + 1); 256 int entry = rand() * (kNumBlocks / RAND_MAX + 1);
247 if (entry >= kNumEntries) 257 if (entry >= kNumBlocks)
248 entry = 0; 258 entry = 0;
249 259
250 files.DeleteBlock(address[entry], false); 260 files.DeleteBlock(address[entry], false);
251 EXPECT_TRUE( 261 EXPECT_TRUE(
252 files.CreateBlock(disk_cache::RANKINGS, BlockSize(), &address[entry])); 262 files.CreateBlock(disk_cache::RANKINGS, BlockSize(), &address[entry]));
253 } 263 }
254 264
255 timer2.Done(); 265 timer2.Done();
256 base::MessageLoop::current()->RunUntilIdle(); 266 base::MessageLoop::current()->RunUntilIdle();
257 delete[] address;
258 } 267 }
259 268
260 } // namespace 269 } // namespace
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698