| 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 "net/disk_cache/stats.h" | 5 #include "net/disk_cache/stats.h" |
| 6 | 6 |
| 7 #include "base/format_macros.h" | 7 #include "base/format_macros.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/metrics/histogram_samples.h" | 9 #include "base/metrics/histogram_samples.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| 11 #include "base/stringprintf.h" | 11 #include "base/stringprintf.h" |
| 12 #include "net/disk_cache/backend_impl.h" | |
| 13 | 12 |
| 14 namespace { | 13 namespace { |
| 15 | 14 |
| 16 const int32 kDiskSignature = 0xF01427E0; | 15 const int32 kDiskSignature = 0xF01427E0; |
| 17 | 16 |
| 18 struct OnDiskStats { | 17 struct OnDiskStats { |
| 19 int32 signature; | 18 int32 signature; |
| 20 int size; | 19 int size; |
| 21 int data_sizes[disk_cache::Stats::kDataSizesLength]; | 20 int data_sizes[disk_cache::Stats::kDataSizesLength]; |
| 22 int64 counters[disk_cache::Stats::MAX_COUNTER]; | 21 int64 counters[disk_cache::Stats::MAX_COUNTER]; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 "Max entries", | 54 "Max entries", |
| 56 "Timer", | 55 "Timer", |
| 57 "Read data", | 56 "Read data", |
| 58 "Write data", | 57 "Write data", |
| 59 "Open rankings", | 58 "Open rankings", |
| 60 "Get rankings", | 59 "Get rankings", |
| 61 "Fatal error", | 60 "Fatal error", |
| 62 "Last report", | 61 "Last report", |
| 63 "Last report timer", | 62 "Last report timer", |
| 64 "Doom recent entries", | 63 "Doom recent entries", |
| 65 "ga.js evicted" | 64 "unused" |
| 66 }; | 65 }; |
| 67 COMPILE_ASSERT(arraysize(kCounterNames) == disk_cache::Stats::MAX_COUNTER, | 66 COMPILE_ASSERT(arraysize(kCounterNames) == disk_cache::Stats::MAX_COUNTER, |
| 68 update_the_names); | 67 update_the_names); |
| 69 | 68 |
| 70 } // namespace | 69 } // namespace |
| 71 | 70 |
| 72 namespace disk_cache { | 71 namespace disk_cache { |
| 73 | 72 |
| 74 bool LoadStats(BackendImpl* backend, Addr address, OnDiskStats* stats) { | 73 bool VerifyStats(OnDiskStats* stats) { |
| 75 MappedFile* file = backend->File(address); | |
| 76 if (!file) | |
| 77 return false; | |
| 78 | |
| 79 size_t offset = address.start_block() * address.BlockSize() + | |
| 80 kBlockHeaderSize; | |
| 81 memset(stats, 0, sizeof(*stats)); | |
| 82 if (!file->Read(stats, sizeof(*stats), offset)) | |
| 83 return false; | |
| 84 | |
| 85 if (stats->signature != kDiskSignature) | 74 if (stats->signature != kDiskSignature) |
| 86 return false; | 75 return false; |
| 87 | 76 |
| 88 // We don't want to discard the whole cache every time we have one extra | 77 // We don't want to discard the whole cache every time we have one extra |
| 89 // counter; we keep old data if we can. | 78 // counter; we keep old data if we can. |
| 90 if (static_cast<unsigned int>(stats->size) > sizeof(*stats)) { | 79 if (static_cast<unsigned int>(stats->size) > sizeof(*stats)) { |
| 91 memset(stats, 0, sizeof(*stats)); | 80 memset(stats, 0, sizeof(*stats)); |
| 92 stats->signature = kDiskSignature; | 81 stats->signature = kDiskSignature; |
| 93 } else if (static_cast<unsigned int>(stats->size) != sizeof(*stats)) { | 82 } else if (static_cast<unsigned int>(stats->size) != sizeof(*stats)) { |
| 94 size_t delta = sizeof(*stats) - static_cast<unsigned int>(stats->size); | 83 size_t delta = sizeof(*stats) - static_cast<unsigned int>(stats->size); |
| 95 memset(reinterpret_cast<char*>(stats) + stats->size, 0, delta); | 84 memset(reinterpret_cast<char*>(stats) + stats->size, 0, delta); |
| 96 stats->size = sizeof(*stats); | 85 stats->size = sizeof(*stats); |
| 97 } | 86 } |
| 98 | 87 |
| 99 return true; | 88 return true; |
| 100 } | 89 } |
| 101 | 90 |
| 102 bool StoreStats(BackendImpl* backend, Addr address, OnDiskStats* stats) { | 91 Stats::Stats() : size_histogram_(NULL) { |
| 103 MappedFile* file = backend->File(address); | |
| 104 if (!file) | |
| 105 return false; | |
| 106 | |
| 107 size_t offset = address.start_block() * address.BlockSize() + | |
| 108 kBlockHeaderSize; | |
| 109 return file->Write(stats, sizeof(*stats), offset); | |
| 110 } | |
| 111 | |
| 112 bool CreateStats(BackendImpl* backend, Addr* address, OnDiskStats* stats) { | |
| 113 if (!backend->CreateBlock(BLOCK_256, 2, address)) | |
| 114 return false; | |
| 115 | |
| 116 // If we have more than 512 bytes of counters, change kDiskSignature so we | |
| 117 // don't overwrite something else (LoadStats must fail). | |
| 118 COMPILE_ASSERT(sizeof(*stats) <= 256 * 2, use_more_blocks); | |
| 119 memset(stats, 0, sizeof(*stats)); | |
| 120 stats->signature = kDiskSignature; | |
| 121 stats->size = sizeof(*stats); | |
| 122 | |
| 123 return StoreStats(backend, *address, stats); | |
| 124 } | |
| 125 | |
| 126 Stats::Stats() : backend_(NULL), size_histogram_(NULL) { | |
| 127 } | 92 } |
| 128 | 93 |
| 129 Stats::~Stats() { | 94 Stats::~Stats() { |
| 130 } | 95 } |
| 131 | 96 |
| 132 bool Stats::Init(BackendImpl* backend, uint32* storage_addr) { | 97 bool Stats::Init(void* data, int num_bytes, Addr address) { |
| 133 OnDiskStats stats; | 98 OnDiskStats local_stats; |
| 134 Addr address(*storage_addr); | 99 OnDiskStats* stats = &local_stats; |
| 135 if (address.is_initialized()) { | 100 if (!num_bytes) { |
| 136 if (!LoadStats(backend, address, &stats)) | 101 memset(stats, 0, sizeof(local_stats)); |
| 102 local_stats.signature = kDiskSignature; |
| 103 local_stats.size = sizeof(local_stats); |
| 104 } else if (num_bytes >= static_cast<int>(sizeof(*stats))) { |
| 105 stats = reinterpret_cast<OnDiskStats*>(data); |
| 106 if (!VerifyStats(stats)) |
| 137 return false; | 107 return false; |
| 138 } else { | 108 } else { |
| 139 if (!CreateStats(backend, &address, &stats)) | 109 return false; |
| 140 return false; | |
| 141 *storage_addr = address.value(); | |
| 142 } | 110 } |
| 143 | 111 |
| 144 storage_addr_ = address.value(); | 112 storage_addr_ = address; |
| 145 backend_ = backend; | |
| 146 | 113 |
| 147 memcpy(data_sizes_, stats.data_sizes, sizeof(data_sizes_)); | 114 memcpy(data_sizes_, stats->data_sizes, sizeof(data_sizes_)); |
| 148 memcpy(counters_, stats.counters, sizeof(counters_)); | 115 memcpy(counters_, stats->counters, sizeof(counters_)); |
| 149 | 116 |
| 117 // Clean up old value. |
| 118 SetCounter(UNUSED, 0); |
| 119 return true; |
| 120 } |
| 121 |
| 122 void Stats::InitSizeHistogram() { |
| 150 // It seems impossible to support this histogram for more than one | 123 // It seems impossible to support this histogram for more than one |
| 151 // simultaneous objects with the current infrastructure. | 124 // simultaneous objects with the current infrastructure. |
| 152 static bool first_time = true; | 125 static bool first_time = true; |
| 153 if (first_time) { | 126 if (first_time) { |
| 154 first_time = false; | 127 first_time = false; |
| 155 // ShouldReportAgain() will re-enter this object. | 128 if (!size_histogram_) { |
| 156 if (!size_histogram_ && backend->cache_type() == net::DISK_CACHE && | |
| 157 backend->ShouldReportAgain()) { | |
| 158 // Stats may be reused when the cache is re-created, but we want only one | 129 // Stats may be reused when the cache is re-created, but we want only one |
| 159 // histogram at any given time. | 130 // histogram at any given time. |
| 160 size_histogram_ = StatsHistogram::FactoryGet("DiskCache.SizeStats", this); | 131 size_histogram_ = StatsHistogram::FactoryGet("DiskCache.SizeStats", this); |
| 161 } | 132 } |
| 162 } | 133 } |
| 134 } |
| 163 | 135 |
| 164 return true; | 136 int Stats::StorageSize() { |
| 137 // If we have more than 512 bytes of counters, change kDiskSignature so we |
| 138 // don't overwrite something else (LoadStats must fail). |
| 139 COMPILE_ASSERT(sizeof(OnDiskStats) <= 256 * 2, use_more_blocks); |
| 140 return 256 * 2; |
| 165 } | 141 } |
| 166 | 142 |
| 167 void Stats::ModifyStorageStats(int32 old_size, int32 new_size) { | 143 void Stats::ModifyStorageStats(int32 old_size, int32 new_size) { |
| 168 // We keep a counter of the data block size on an array where each entry is | 144 // We keep a counter of the data block size on an array where each entry is |
| 169 // the adjusted log base 2 of the size. The first entry counts blocks of 256 | 145 // the adjusted log base 2 of the size. The first entry counts blocks of 256 |
| 170 // bytes, the second blocks up to 512 bytes, etc. With 20 entries, the last | 146 // bytes, the second blocks up to 512 bytes, etc. With 20 entries, the last |
| 171 // one stores entries of more than 64 MB | 147 // one stores entries of more than 64 MB |
| 172 int new_index = GetStatsBucket(new_size); | 148 int new_index = GetStatsBucket(new_size); |
| 173 int old_index = GetStatsBucket(old_size); | 149 int old_index = GetStatsBucket(old_size); |
| 174 | 150 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 int Stats::GetLargeEntriesSize() { | 203 int Stats::GetLargeEntriesSize() { |
| 228 int total = 0; | 204 int total = 0; |
| 229 // data_sizes_[20] stores values between 512 KB and 1 MB (see comment before | 205 // data_sizes_[20] stores values between 512 KB and 1 MB (see comment before |
| 230 // GetStatsBucket()). | 206 // GetStatsBucket()). |
| 231 for (int bucket = 20; bucket < kDataSizesLength; bucket++) | 207 for (int bucket = 20; bucket < kDataSizesLength; bucket++) |
| 232 total += data_sizes_[bucket] * GetBucketRange(bucket); | 208 total += data_sizes_[bucket] * GetBucketRange(bucket); |
| 233 | 209 |
| 234 return total; | 210 return total; |
| 235 } | 211 } |
| 236 | 212 |
| 237 void Stats::Store() { | 213 int Stats::SerializeStats(void* data, int num_bytes, Addr* address) { |
| 238 if (!backend_) | 214 OnDiskStats* stats = reinterpret_cast<OnDiskStats*>(data); |
| 239 return; | 215 if (num_bytes < static_cast<int>(sizeof(*stats))) |
| 216 return 0; |
| 240 | 217 |
| 241 OnDiskStats stats; | 218 stats->signature = kDiskSignature; |
| 242 stats.signature = kDiskSignature; | 219 stats->size = sizeof(*stats); |
| 243 stats.size = sizeof(stats); | 220 memcpy(stats->data_sizes, data_sizes_, sizeof(data_sizes_)); |
| 244 memcpy(stats.data_sizes, data_sizes_, sizeof(data_sizes_)); | 221 memcpy(stats->counters, counters_, sizeof(counters_)); |
| 245 memcpy(stats.counters, counters_, sizeof(counters_)); | |
| 246 | 222 |
| 247 Addr address(storage_addr_); | 223 *address = storage_addr_; |
| 248 StoreStats(backend_, address, &stats); | 224 return sizeof(*stats); |
| 249 } | 225 } |
| 250 | 226 |
| 251 int Stats::GetBucketRange(size_t i) const { | 227 int Stats::GetBucketRange(size_t i) const { |
| 252 if (i < 2) | 228 if (i < 2) |
| 253 return static_cast<int>(1024 * i); | 229 return static_cast<int>(1024 * i); |
| 254 | 230 |
| 255 if (i < 12) | 231 if (i < 12) |
| 256 return static_cast<int>(2048 * (i - 1)); | 232 return static_cast<int>(2048 * (i - 1)); |
| 257 | 233 |
| 258 if (i < 17) | 234 if (i < 17) |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 int Stats::GetRatio(Counters hit, Counters miss) const { | 300 int Stats::GetRatio(Counters hit, Counters miss) const { |
| 325 int64 ratio = GetCounter(hit) * 100; | 301 int64 ratio = GetCounter(hit) * 100; |
| 326 if (!ratio) | 302 if (!ratio) |
| 327 return 0; | 303 return 0; |
| 328 | 304 |
| 329 ratio /= (GetCounter(hit) + GetCounter(miss)); | 305 ratio /= (GetCounter(hit) + GetCounter(miss)); |
| 330 return static_cast<int>(ratio); | 306 return static_cast<int>(ratio); |
| 331 } | 307 } |
| 332 | 308 |
| 333 } // namespace disk_cache | 309 } // namespace disk_cache |
| OLD | NEW |