OLD | NEW |
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 <limits> | 5 #include <limits> |
6 #include <string> | 6 #include <string> |
7 | 7 |
| 8 #include "base/barrier_closure.h" |
8 #include "base/bind.h" | 9 #include "base/bind.h" |
9 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
10 #include "base/files/file_enumerator.h" | 11 #include "base/files/file_enumerator.h" |
11 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
12 #include "base/hash.h" | 13 #include "base/hash.h" |
13 #include "base/process/process_metrics.h" | 14 #include "base/process/process_metrics.h" |
14 #include "base/rand_util.h" | 15 #include "base/rand_util.h" |
15 #include "base/run_loop.h" | 16 #include "base/run_loop.h" |
| 17 #include "base/strings/string_number_conversions.h" |
16 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
17 #include "base/test/perf_time_logger.h" | 19 #include "base/test/perf_time_logger.h" |
18 #include "base/test/scoped_task_environment.h" | 20 #include "base/test/scoped_task_environment.h" |
19 #include "base/test/test_file_util.h" | 21 #include "base/test/test_file_util.h" |
20 #include "base/threading/thread.h" | 22 #include "base/threading/thread.h" |
21 #include "net/base/cache_type.h" | 23 #include "net/base/cache_type.h" |
22 #include "net/base/io_buffer.h" | 24 #include "net/base/io_buffer.h" |
23 #include "net/base/net_errors.h" | 25 #include "net/base/net_errors.h" |
24 #include "net/base/test_completion_callback.h" | 26 #include "net/base/test_completion_callback.h" |
25 #include "net/disk_cache/backend_cleanup_tracker.h" | 27 #include "net/disk_cache/backend_cleanup_tracker.h" |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 | 297 |
296 files.DeleteBlock(address[entry], false); | 298 files.DeleteBlock(address[entry], false); |
297 EXPECT_TRUE( | 299 EXPECT_TRUE( |
298 files.CreateBlock(disk_cache::RANKINGS, block_size, &address[entry])); | 300 files.CreateBlock(disk_cache::RANKINGS, block_size, &address[entry])); |
299 } | 301 } |
300 | 302 |
301 timer2.Done(); | 303 timer2.Done(); |
302 base::RunLoop().RunUntilIdle(); | 304 base::RunLoop().RunUntilIdle(); |
303 } | 305 } |
304 | 306 |
| 307 void VerifyRvAndCallClosure(base::Closure* c, int expect_rv, int rv) { |
| 308 EXPECT_EQ(expect_rv, rv); |
| 309 c->Run(); |
| 310 } |
| 311 |
| 312 TEST_F(DiskCachePerfTest, SimpleCacheInitialReadPortion) { |
| 313 // A benchmark that aims to measure how much time we take in I/O thread |
| 314 // for initial bookkeeping before returning to the caller, and how much |
| 315 // after (batched up some). The later portion includes some event loop |
| 316 // overhead. |
| 317 const int kBatchSize = 100; |
| 318 |
| 319 SetSimpleCacheMode(); |
| 320 |
| 321 InitCache(); |
| 322 // Write out the entries, and keep their objects around. |
| 323 scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kHeadersSize)); |
| 324 scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kBodySize)); |
| 325 |
| 326 CacheTestFillBuffer(buffer1->data(), kHeadersSize, false); |
| 327 CacheTestFillBuffer(buffer2->data(), kBodySize, false); |
| 328 |
| 329 disk_cache::Entry* cache_entry[kBatchSize]; |
| 330 for (int i = 0; i < kBatchSize; ++i) { |
| 331 net::TestCompletionCallback cb; |
| 332 int rv = cache_->CreateEntry(base::IntToString(i), &cache_entry[i], |
| 333 cb.callback()); |
| 334 ASSERT_EQ(net::OK, cb.GetResult(rv)); |
| 335 |
| 336 rv = cache_entry[i]->WriteData(0, 0, buffer1.get(), kHeadersSize, |
| 337 cb.callback(), false); |
| 338 ASSERT_EQ(kHeadersSize, cb.GetResult(rv)); |
| 339 rv = cache_entry[i]->WriteData(1, 0, buffer2.get(), kBodySize, |
| 340 cb.callback(), false); |
| 341 ASSERT_EQ(kBodySize, cb.GetResult(rv)); |
| 342 } |
| 343 |
| 344 // Now repeatedly read these, batching up the waiting to try to |
| 345 // account for the two portions separately. Note that we need separate entries |
| 346 // since we are trying to keep interesting work from being on the delayed-done |
| 347 // portion. |
| 348 const int kIterations = 50000; |
| 349 |
| 350 double elapsed_early = 0.0; |
| 351 double elapsed_late = 0.0; |
| 352 |
| 353 for (int i = 0; i < kIterations; ++i) { |
| 354 base::RunLoop event_loop; |
| 355 base::Closure barrier = |
| 356 base::BarrierClosure(kBatchSize, event_loop.QuitWhenIdleClosure()); |
| 357 net::CompletionCallback cb_batch(base::Bind( |
| 358 VerifyRvAndCallClosure, base::Unretained(&barrier), kHeadersSize)); |
| 359 |
| 360 base::ElapsedTimer timer_early; |
| 361 for (int e = 0; e < kBatchSize; ++e) { |
| 362 int rv = |
| 363 cache_entry[e]->ReadData(0, 0, buffer1.get(), kHeadersSize, cb_batch); |
| 364 if (rv != net::ERR_IO_PENDING) { |
| 365 barrier.Run(); |
| 366 ASSERT_EQ(kHeadersSize, rv); |
| 367 } |
| 368 } |
| 369 elapsed_early += timer_early.Elapsed().InMillisecondsF(); |
| 370 |
| 371 base::ElapsedTimer timer_late; |
| 372 event_loop.Run(); |
| 373 elapsed_late += timer_late.Elapsed().InMillisecondsF(); |
| 374 } |
| 375 |
| 376 // Cleanup |
| 377 for (int i = 0; i < kBatchSize; ++i) |
| 378 cache_entry[i]->Close(); |
| 379 |
| 380 disk_cache::SimpleBackendImpl::FlushWorkerPoolForTesting(); |
| 381 base::RunLoop().RunUntilIdle(); |
| 382 LOG(ERROR) << "Early portion:" << elapsed_early << " ms"; |
| 383 LOG(ERROR) << "\tPer entry:" |
| 384 << 1000 * (elapsed_early / (kIterations * kBatchSize)) << " us"; |
| 385 LOG(ERROR) << "Event loop portion: " << elapsed_late << " ms"; |
| 386 LOG(ERROR) << "\tPer entry:" |
| 387 << 1000 * (elapsed_late / (kIterations * kBatchSize)) << " us"; |
| 388 } |
| 389 |
305 // Measures how quickly SimpleIndex can compute which entries to evict. | 390 // Measures how quickly SimpleIndex can compute which entries to evict. |
306 TEST(SimpleIndexPerfTest, EvictionPerformance) { | 391 TEST(SimpleIndexPerfTest, EvictionPerformance) { |
307 const int kEntries = 10000; | 392 const int kEntries = 10000; |
308 | 393 |
309 class NoOpDelegate : public disk_cache::SimpleIndexDelegate { | 394 class NoOpDelegate : public disk_cache::SimpleIndexDelegate { |
310 void DoomEntries(std::vector<uint64_t>* entry_hashes, | 395 void DoomEntries(std::vector<uint64_t>* entry_hashes, |
311 const net::CompletionCallback& callback) override {} | 396 const net::CompletionCallback& callback) override {} |
312 }; | 397 }; |
313 | 398 |
314 NoOpDelegate delegate; | 399 NoOpDelegate delegate; |
(...skipping 22 matching lines...) Expand all Loading... |
337 index.SetMaxSize(kEntries); | 422 index.SetMaxSize(kEntries); |
338 index.UpdateEntrySize(0, 1u); | 423 index.UpdateEntrySize(0, 1u); |
339 evict_elapsed_ms += timer.Elapsed().InMillisecondsF(); | 424 evict_elapsed_ms += timer.Elapsed().InMillisecondsF(); |
340 } | 425 } |
341 | 426 |
342 LOG(ERROR) << "Average time to evict:" << (evict_elapsed_ms / iterations) | 427 LOG(ERROR) << "Average time to evict:" << (evict_elapsed_ms / iterations) |
343 << "ms"; | 428 << "ms"; |
344 } | 429 } |
345 | 430 |
346 } // namespace | 431 } // namespace |
OLD | NEW |