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 |