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

Side by Side Diff: base/metrics/histogram.cc

Issue 6577013: Crash when we notice a corruption of the histogram range-vector... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « base/metrics/histogram.h ('k') | base/metrics/histogram_unittest.cc » ('j') | 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) 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
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
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
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
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
OLDNEW
« no previous file with comments | « base/metrics/histogram.h ('k') | base/metrics/histogram_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698