OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 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 | 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 // Histogram is an object that aggregates statistics, and can summarize them in | 5 // Histogram is an object that aggregates statistics, and can summarize them in |
6 // various forms, including ASCII graphical, HTML, and numerically (as a | 6 // various forms, including ASCII graphical, HTML, and numerically (as a |
7 // vector of numbers corresponding to each of the aggregating buckets). | 7 // vector of numbers corresponding to each of the aggregating buckets). |
8 // See header file for details and examples. | 8 // See header file for details and examples. |
9 | 9 |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
11 | 11 |
12 #include <math.h> | 12 #include <math.h> |
13 | 13 |
14 #include <algorithm> | 14 #include <algorithm> |
15 #include <string> | 15 #include <string> |
16 | 16 |
17 #include "base/logging.h" | 17 #include "base/logging.h" |
18 #include "base/pickle.h" | 18 #include "base/pickle.h" |
19 #include "base/stringprintf.h" | 19 #include "base/stringprintf.h" |
20 #include "base/synchronization/lock.h" | 20 #include "base/synchronization/lock.h" |
21 | 21 |
22 namespace base { | 22 namespace base { |
23 | 23 |
24 // Static table of checksums for all possible 8 bit bytes. | |
25 const uint32 Histogram::kCrcTable[256] = {0x0, 0x77073096L, 0xee0e612cL, | |
Mike Belshe
2011/02/25 01:21:18
this table is duplicated in src/third_party/zlib/c
jar (doing other things)
2011/02/26 17:19:55
Reaching from base into the third party libraries
| |
26 0x990951baL, 0x76dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0xedb8832L, | |
27 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x9b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, | |
28 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, | |
29 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, | |
30 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, | |
31 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, | |
32 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, | |
33 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 0xc8d75180L, | |
34 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, | |
35 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, | |
36 0xb6662d3dL, 0x76dc4190L, 0x1db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, | |
37 0x6b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0xf00f934L, 0x9609a88eL, | |
38 0xe10e9818L, 0x7f6a0dbbL, 0x86d3d2dL, 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, | |
39 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, | |
40 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, | |
41 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, | |
42 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, | |
43 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, | |
44 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, | |
45 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, | |
46 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, | |
47 0x9abfb3b6L, 0x3b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x4db2615L, | |
48 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0xd6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, | |
49 0x9309ff9dL, 0xa00ae27L, 0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, | |
50 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, | |
51 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, | |
52 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, | |
53 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, | |
54 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, | |
55 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, | |
56 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, | |
57 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, | |
58 0x26d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x5005713L, 0x95bf4a82L, | |
59 0xe2b87a14L, 0x7bb12baeL, 0xcb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, | |
60 0xbdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, | |
61 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, | |
62 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, | |
63 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, | |
64 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, | |
65 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, | |
66 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, | |
67 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, | |
68 0x2d02ef8dL, | |
69 }; | |
70 | |
24 typedef Histogram::Count Count; | 71 typedef Histogram::Count Count; |
25 | 72 |
26 // static | 73 // static |
27 const size_t Histogram::kBucketCount_MAX = 10000u; | 74 const size_t Histogram::kBucketCount_MAX = 10000u; |
28 | 75 |
29 scoped_refptr<Histogram> Histogram::FactoryGet(const std::string& name, | 76 scoped_refptr<Histogram> Histogram::FactoryGet(const std::string& name, |
30 Sample minimum, Sample maximum, size_t bucket_count, Flags flags) { | 77 Sample minimum, Sample maximum, size_t bucket_count, Flags flags) { |
31 scoped_refptr<Histogram> histogram(NULL); | 78 scoped_refptr<Histogram> histogram(NULL); |
32 | 79 |
33 // Defensive code. | 80 // Defensive code. |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
154 // static | 201 // static |
155 std::string Histogram::SerializeHistogramInfo(const Histogram& histogram, | 202 std::string Histogram::SerializeHistogramInfo(const Histogram& histogram, |
156 const SampleSet& snapshot) { | 203 const SampleSet& snapshot) { |
157 DCHECK_NE(NOT_VALID_IN_RENDERER, histogram.histogram_type()); | 204 DCHECK_NE(NOT_VALID_IN_RENDERER, histogram.histogram_type()); |
158 | 205 |
159 Pickle pickle; | 206 Pickle pickle; |
160 pickle.WriteString(histogram.histogram_name()); | 207 pickle.WriteString(histogram.histogram_name()); |
161 pickle.WriteInt(histogram.declared_min()); | 208 pickle.WriteInt(histogram.declared_min()); |
162 pickle.WriteInt(histogram.declared_max()); | 209 pickle.WriteInt(histogram.declared_max()); |
163 pickle.WriteSize(histogram.bucket_count()); | 210 pickle.WriteSize(histogram.bucket_count()); |
164 pickle.WriteInt(histogram.range_checksum()); | 211 pickle.WriteUInt32(histogram.range_checksum()); |
165 pickle.WriteInt(histogram.histogram_type()); | 212 pickle.WriteInt(histogram.histogram_type()); |
166 pickle.WriteInt(histogram.flags()); | 213 pickle.WriteInt(histogram.flags()); |
167 | 214 |
168 snapshot.Serialize(&pickle); | 215 snapshot.Serialize(&pickle); |
169 return std::string(static_cast<const char*>(pickle.data()), pickle.size()); | 216 return std::string(static_cast<const char*>(pickle.data()), pickle.size()); |
170 } | 217 } |
171 | 218 |
172 // static | 219 // static |
173 bool Histogram::DeserializeHistogramInfo(const std::string& histogram_info) { | 220 bool Histogram::DeserializeHistogramInfo(const std::string& histogram_info) { |
174 if (histogram_info.empty()) { | 221 if (histogram_info.empty()) { |
175 return false; | 222 return false; |
176 } | 223 } |
177 | 224 |
178 Pickle pickle(histogram_info.data(), | 225 Pickle pickle(histogram_info.data(), |
179 static_cast<int>(histogram_info.size())); | 226 static_cast<int>(histogram_info.size())); |
180 std::string histogram_name; | 227 std::string histogram_name; |
181 int declared_min; | 228 int declared_min; |
182 int declared_max; | 229 int declared_max; |
183 size_t bucket_count; | 230 size_t bucket_count; |
184 int range_checksum; | 231 uint32 range_checksum; |
185 int histogram_type; | 232 int histogram_type; |
186 int pickle_flags; | 233 int pickle_flags; |
187 SampleSet sample; | 234 SampleSet sample; |
188 | 235 |
189 void* iter = NULL; | 236 void* iter = NULL; |
190 if (!pickle.ReadString(&iter, &histogram_name) || | 237 if (!pickle.ReadString(&iter, &histogram_name) || |
191 !pickle.ReadInt(&iter, &declared_min) || | 238 !pickle.ReadInt(&iter, &declared_min) || |
192 !pickle.ReadInt(&iter, &declared_max) || | 239 !pickle.ReadInt(&iter, &declared_max) || |
193 !pickle.ReadSize(&iter, &bucket_count) || | 240 !pickle.ReadSize(&iter, &bucket_count) || |
194 !pickle.ReadInt(&iter, &range_checksum) || | 241 !pickle.ReadUInt32(&iter, &range_checksum) || |
195 !pickle.ReadInt(&iter, &histogram_type) || | 242 !pickle.ReadInt(&iter, &histogram_type) || |
196 !pickle.ReadInt(&iter, &pickle_flags) || | 243 !pickle.ReadInt(&iter, &pickle_flags) || |
197 !sample.Histogram::SampleSet::Deserialize(&iter, pickle)) { | 244 !sample.Histogram::SampleSet::Deserialize(&iter, pickle)) { |
198 LOG(ERROR) << "Pickle error decoding Histogram: " << histogram_name; | 245 LOG(ERROR) << "Pickle error decoding Histogram: " << histogram_name; |
199 return false; | 246 return false; |
200 } | 247 } |
201 DCHECK(pickle_flags & kIPCSerializationSourceFlag); | 248 DCHECK(pickle_flags & kIPCSerializationSourceFlag); |
202 // Since these fields may have come from an untrusted renderer, do additional | 249 // Since these fields may have come from an untrusted renderer, do additional |
203 // checks above and beyond those in Histogram::Initialize() | 250 // checks above and beyond those in Histogram::Initialize() |
204 if (declared_max <= 0 || declared_min <= 0 || declared_max < declared_min || | 251 if (declared_max <= 0 || declared_min <= 0 || declared_max < declared_min || |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
245 } | 292 } |
246 | 293 |
247 //------------------------------------------------------------------------------ | 294 //------------------------------------------------------------------------------ |
248 // Methods for the validating a sample and a related histogram. | 295 // Methods for the validating a sample and a related histogram. |
249 //------------------------------------------------------------------------------ | 296 //------------------------------------------------------------------------------ |
250 | 297 |
251 Histogram::Inconsistencies Histogram::FindCorruption( | 298 Histogram::Inconsistencies Histogram::FindCorruption( |
252 const SampleSet& snapshot) const { | 299 const SampleSet& snapshot) const { |
253 int inconsistencies = NO_INCONSISTENCIES; | 300 int inconsistencies = NO_INCONSISTENCIES; |
254 Sample previous_range = -1; // Bottom range is always 0. | 301 Sample previous_range = -1; // Bottom range is always 0. |
255 Sample checksum = 0; | |
256 int64 count = 0; | 302 int64 count = 0; |
257 for (size_t index = 0; index < bucket_count(); ++index) { | 303 for (size_t index = 0; index < bucket_count(); ++index) { |
258 count += snapshot.counts(index); | 304 count += snapshot.counts(index); |
259 int new_range = ranges(index); | 305 int new_range = ranges(index); |
260 checksum += new_range; | |
261 if (previous_range >= new_range) | 306 if (previous_range >= new_range) |
262 inconsistencies |= BUCKET_ORDER_ERROR; | 307 inconsistencies |= BUCKET_ORDER_ERROR; |
263 previous_range = new_range; | 308 previous_range = new_range; |
264 } | 309 } |
265 | 310 |
266 if (checksum != range_checksum_) | 311 if (CalculateRangeChecksum() != range_checksum_) |
267 inconsistencies |= RANGE_CHECKSUM_ERROR; | 312 inconsistencies |= RANGE_CHECKSUM_ERROR; |
268 | 313 |
269 int64 delta64 = snapshot.redundant_count() - count; | 314 int64 delta64 = snapshot.redundant_count() - count; |
270 if (delta64 != 0) { | 315 if (delta64 != 0) { |
271 int delta = static_cast<int>(delta64); | 316 int delta = static_cast<int>(delta64); |
272 if (delta != delta64) | 317 if (delta != delta64) |
273 delta = INT_MAX; // Flag all giant errors as INT_MAX. | 318 delta = INT_MAX; // Flag all giant errors as INT_MAX. |
274 // Since snapshots of histograms are taken asynchronously relative to | 319 // Since snapshots of histograms are taken asynchronously relative to |
275 // sampling (and snapped from different threads), it is pretty likely that | 320 // sampling (and snapped from different threads), it is pretty likely that |
276 // we'll catch a redundant count that doesn't match the sample count. We | 321 // we'll catch a redundant count that doesn't match the sample count. We |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
493 ranges_[bucket_count_] = kSampleType_MAX; | 538 ranges_[bucket_count_] = kSampleType_MAX; |
494 InitializeBucketRange(); | 539 InitializeBucketRange(); |
495 DCHECK(ValidateBucketRanges()); | 540 DCHECK(ValidateBucketRanges()); |
496 StatisticsRecorder::Register(this); | 541 StatisticsRecorder::Register(this); |
497 } | 542 } |
498 | 543 |
499 bool Histogram::HasValidRangeChecksum() const { | 544 bool Histogram::HasValidRangeChecksum() const { |
500 return CalculateRangeChecksum() == range_checksum_; | 545 return CalculateRangeChecksum() == range_checksum_; |
501 } | 546 } |
502 | 547 |
503 Histogram::Sample Histogram::CalculateRangeChecksum() const { | 548 uint32 Histogram::CalculateRangeChecksum() const { |
504 DCHECK_EQ(ranges_.size(), bucket_count() + 1); | 549 DCHECK_EQ(ranges_.size(), bucket_count() + 1); |
505 Sample checksum = 0; | 550 uint32 checksum = static_cast<uint32>(ranges_.size()); // Seed checksum. |
506 for (size_t index = 0; index < bucket_count(); ++index) { | 551 for (size_t index = 0; index < bucket_count(); ++index) |
507 checksum += ranges(index); | 552 checksum = Crc32(checksum, ranges(index)); |
508 } | |
509 return checksum; | 553 return checksum; |
510 } | 554 } |
511 | 555 |
556 // We generate the CRC-32 using the low order bits to select whether to XOR in | |
557 // the reversed polynomial 0xedb88320L. This is nice and simple, and allows us | |
558 // to keep the quotient in a uint32. Since we're not concerned about the nature | |
559 // of corruptions (i.e., we don't care about bit sequencing, since we are | |
560 // handling memory changes, which are more grotesque) so we don't bother to | |
561 // get the CRC correct for big-endian vs little-ending calculations. All we | |
562 // need is a nice hash, that tends to depend on all the bits of the sample, with | |
563 // very little chance of changes in one place impacting changes in another | |
564 // place. | |
565 uint32 Histogram::Crc32(uint32 sum, Histogram::Sample range) { | |
566 union { | |
567 Histogram::Sample range; | |
568 char bytes[sizeof(Histogram::Sample)]; | |
569 } converter; | |
570 converter.range = range; | |
571 for (size_t i = 0; i < sizeof(converter); ++i) | |
572 sum = kCrcTable[(sum & 0xff) ^ converter.bytes[i]] ^ (sum >> 8); | |
Mike Belshe
2011/02/25 01:21:18
I think this line must be wrong.
kCrcTable is onl
jar (doing other things)
2011/02/26 17:19:55
Added "unsigned" to declaration of bytes per our d
| |
573 return sum; | |
574 | |
Mike Belshe
2011/02/25 01:21:18
nit: blank line
jar (doing other things)
2011/02/26 17:19:55
Done.
| |
575 } | |
576 | |
512 //------------------------------------------------------------------------------ | 577 //------------------------------------------------------------------------------ |
513 // Private methods | 578 // Private methods |
514 | 579 |
515 double Histogram::GetPeakBucketSize(const SampleSet& snapshot) const { | 580 double Histogram::GetPeakBucketSize(const SampleSet& snapshot) const { |
516 double max = 0; | 581 double max = 0; |
517 for (size_t i = 0; i < bucket_count() ; ++i) { | 582 for (size_t i = 0; i < bucket_count() ; ++i) { |
518 double current_size = GetBucketSize(snapshot.counts(i), i); | 583 double current_size = GetBucketSize(snapshot.counts(i), i); |
519 if (current_size > max) | 584 if (current_size > max) |
520 max = current_size; | 585 max = current_size; |
521 } | 586 } |
(...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1047 } | 1112 } |
1048 | 1113 |
1049 // static | 1114 // static |
1050 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; | 1115 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; |
1051 // static | 1116 // static |
1052 base::Lock* StatisticsRecorder::lock_ = NULL; | 1117 base::Lock* StatisticsRecorder::lock_ = NULL; |
1053 // static | 1118 // static |
1054 bool StatisticsRecorder::dump_on_exit_ = false; | 1119 bool StatisticsRecorder::dump_on_exit_ = false; |
1055 | 1120 |
1056 } // namespace base | 1121 } // namespace base |
OLD | NEW |