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

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

Issue 4174002: Try to detect internal corruption of histogram instances.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 1 month 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 | « no previous file | base/metrics/histogram.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 8
9 // It supports calls to accumulate either time intervals (which are processed 9 // It supports calls to accumulate either time intervals (which are processed
10 // as integral number of milliseconds), or arbitrary integral units. 10 // as integral number of milliseconds), or arbitrary integral units.
(...skipping 18 matching lines...) Expand all
29 // gigantic range with the addition of very few buckets. 29 // gigantic range with the addition of very few buckets.
30 30
31 #ifndef BASE_METRICS_HISTOGRAM_H_ 31 #ifndef BASE_METRICS_HISTOGRAM_H_
32 #define BASE_METRICS_HISTOGRAM_H_ 32 #define BASE_METRICS_HISTOGRAM_H_
33 #pragma once 33 #pragma once
34 34
35 #include <map> 35 #include <map>
36 #include <string> 36 #include <string>
37 #include <vector> 37 #include <vector>
38 38
39 #include "base/gtest_prod_util.h"
39 #include "base/ref_counted.h" 40 #include "base/ref_counted.h"
40 #include "base/logging.h" 41 #include "base/logging.h"
41 #include "base/time.h" 42 #include "base/time.h"
42 43
43 class Lock; 44 class Lock;
44 class Pickle; 45 class Pickle;
45 46
46 namespace base { 47 namespace base {
47 48
48 //------------------------------------------------------------------------------ 49 //------------------------------------------------------------------------------
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 237
237 class Histogram : public base::RefCountedThreadSafe<Histogram> { 238 class Histogram : public base::RefCountedThreadSafe<Histogram> {
238 public: 239 public:
239 typedef int Sample; // Used for samples (and ranges of samples). 240 typedef int Sample; // Used for samples (and ranges of samples).
240 typedef int Count; // Used to count samples in a bucket. 241 typedef int Count; // Used to count samples in a bucket.
241 static const Sample kSampleType_MAX = INT_MAX; 242 static const Sample kSampleType_MAX = INT_MAX;
242 243
243 typedef std::vector<Count> Counts; 244 typedef std::vector<Count> Counts;
244 typedef std::vector<Sample> Ranges; 245 typedef std::vector<Sample> Ranges;
245 246
246 /* These enums are meant to facilitate deserialization of renderer histograms 247 // These enums are used to facilitate deserialization of renderer histograms
247 into the browser. */ 248 // into the browser.
248 enum ClassType { 249 enum ClassType {
249 HISTOGRAM, 250 HISTOGRAM,
250 LINEAR_HISTOGRAM, 251 LINEAR_HISTOGRAM,
251 BOOLEAN_HISTOGRAM, 252 BOOLEAN_HISTOGRAM,
252 CUSTOM_HISTOGRAM, 253 CUSTOM_HISTOGRAM,
253 NOT_VALID_IN_RENDERER 254 NOT_VALID_IN_RENDERER
254 }; 255 };
255 256
256 enum BucketLayout { 257 enum BucketLayout {
257 EXPONENTIAL, 258 EXPONENTIAL,
258 LINEAR, 259 LINEAR,
259 CUSTOM 260 CUSTOM
260 }; 261 };
261 262
262 enum Flags { 263 enum Flags {
263 kNoFlags = 0, 264 kNoFlags = 0,
264 kUmaTargetedHistogramFlag = 0x1, // Histogram should be UMA uploaded. 265 kUmaTargetedHistogramFlag = 0x1, // Histogram should be UMA uploaded.
265 266
266 // Indicate that the histogram was pickled to be sent across an IPC Channel. 267 // Indicate that the histogram was pickled to be sent across an IPC Channel.
267 // If we observe this flag on a histogram being aggregated into after IPC, 268 // If we observe this flag on a histogram being aggregated into after IPC,
268 // then we are running in a single process mode, and the aggregation should 269 // then we are running in a single process mode, and the aggregation should
269 // not take place (as we would be aggregating back into the source 270 // not take place (as we would be aggregating back into the source
270 // histogram!). 271 // histogram!).
271 kIPCSerializationSourceFlag = 0x10, 272 kIPCSerializationSourceFlag = 0x10,
272 273
273 kHexRangePrintingFlag = 0x8000, // Fancy bucket-naming supported. 274 kHexRangePrintingFlag = 0x8000, // Fancy bucket-naming supported.
274 }; 275 };
275 276
277 enum Inconsistencies {
278 NO_INCONSISTENCIES = 0x0,
279 RANGE_CHECKSUM_ERROR = 0x1,
280 BUCKET_ORDER_ERROR = 0x2,
281 COUNT_HIGH_ERROR = 0x4,
282 COUNT_LOW_ERROR = 0x8,
283
284 NEVER_EXCEEDED_VALUE = 0x10
285 };
286
276 struct DescriptionPair { 287 struct DescriptionPair {
277 Sample sample; 288 Sample sample;
278 const char* description; // Null means end of a list of pairs. 289 const char* description; // Null means end of a list of pairs.
279 }; 290 };
280 291
281 //---------------------------------------------------------------------------- 292 //----------------------------------------------------------------------------
282 // Statistic values, developed over the life of the histogram. 293 // Statistic values, developed over the life of the histogram.
283 294
284 class SampleSet { 295 class SampleSet {
285 public: 296 public:
286 explicit SampleSet(); 297 explicit SampleSet();
287 ~SampleSet(); 298 ~SampleSet();
288 299
289 // Adjust size of counts_ for use with given histogram. 300 // Adjust size of counts_ for use with given histogram.
290 void Resize(const Histogram& histogram); 301 void Resize(const Histogram& histogram);
291 void CheckSize(const Histogram& histogram) const; 302 void CheckSize(const Histogram& histogram) const;
292 303
293 // Accessor for histogram to make routine additions. 304 // Accessor for histogram to make routine additions.
294 void Accumulate(Sample value, Count count, size_t index); 305 void Accumulate(Sample value, Count count, size_t index);
295 306
296 // Accessor methods. 307 // Accessor methods.
297 Count counts(size_t i) const { return counts_[i]; } 308 Count counts(size_t i) const { return counts_[i]; }
298 Count TotalCount() const; 309 Count TotalCount() const;
299 int64 sum() const { return sum_; } 310 int64 sum() const { return sum_; }
300 int64 square_sum() const { return square_sum_; } 311 int64 square_sum() const { return square_sum_; }
312 int64 redundant_count() const { return redundant_count_; }
301 313
302 // Arithmetic manipulation of corresponding elements of the set. 314 // Arithmetic manipulation of corresponding elements of the set.
303 void Add(const SampleSet& other); 315 void Add(const SampleSet& other);
304 void Subtract(const SampleSet& other); 316 void Subtract(const SampleSet& other);
305 317
306 bool Serialize(Pickle* pickle) const; 318 bool Serialize(Pickle* pickle) const;
307 bool Deserialize(void** iter, const Pickle& pickle); 319 bool Deserialize(void** iter, const Pickle& pickle);
308 320
309 protected: 321 protected:
310 // Actual histogram data is stored in buckets, showing the count of values 322 // Actual histogram data is stored in buckets, showing the count of values
311 // that fit into each bucket. 323 // that fit into each bucket.
312 Counts counts_; 324 Counts counts_;
313 325
314 // Save simple stats locally. Note that this MIGHT get done in base class 326 // Save simple stats locally. Note that this MIGHT get done in base class
315 // without shared memory at some point. 327 // without shared memory at some point.
316 int64 sum_; // sum of samples. 328 int64 sum_; // sum of samples.
317 int64 square_sum_; // sum of squares of samples. 329 int64 square_sum_; // sum of squares of samples.
330
331 private:
332 // Allow tests to corrupt our innards for testing purposes.
333 FRIEND_TEST(HistogramTest, CorruptSampleCounts);
334
335 // To help identify memory corruption, we reduntantly save the number of
336 // samples we've accumulated into all of our buckets. We can compare this
337 // count to the sum of the counts in all buckets, and detect problems. Note
338 // that due to races in histogram accumulation (if a histogram is indeed
339 // updated on several threads simultaneously), the tallies might mismatch,
340 // and also the snapshotting code may asynchronously get a mismatch (though
341 // generally either race based mismatch cause is VERY rare).
342 int64 redundant_count_;
318 }; 343 };
344
319 //---------------------------------------------------------------------------- 345 //----------------------------------------------------------------------------
320 // minimum should start from 1. 0 is invalid as a minimum. 0 is an implicit 346 // minimum should start from 1. 0 is invalid as a minimum. 0 is an implicit
321 // default underflow bucket. 347 // default underflow bucket.
322 static scoped_refptr<Histogram> FactoryGet(const std::string& name, 348 static scoped_refptr<Histogram> FactoryGet(const std::string& name,
323 Sample minimum, Sample maximum, size_t bucket_count, Flags flags); 349 Sample minimum, Sample maximum, size_t bucket_count, Flags flags);
324 static scoped_refptr<Histogram> FactoryTimeGet(const std::string& name, 350 static scoped_refptr<Histogram> FactoryTimeGet(const std::string& name,
325 base::TimeDelta minimum, base::TimeDelta maximum, size_t bucket_count, 351 base::TimeDelta minimum, base::TimeDelta maximum, size_t bucket_count,
326 Flags flags); 352 Flags flags);
327 353
328 void Add(int value); 354 void Add(int value);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 386
361 // Serialize the given snapshot of a Histogram into a String. Uses 387 // Serialize the given snapshot of a Histogram into a String. Uses
362 // Pickle class to flatten the object. 388 // Pickle class to flatten the object.
363 static std::string SerializeHistogramInfo(const Histogram& histogram, 389 static std::string SerializeHistogramInfo(const Histogram& histogram,
364 const SampleSet& snapshot); 390 const SampleSet& snapshot);
365 // The following method accepts a list of pickled histograms and 391 // The following method accepts a list of pickled histograms and
366 // builds a histogram and updates shadow copy of histogram data in the 392 // builds a histogram and updates shadow copy of histogram data in the
367 // browser process. 393 // browser process.
368 static bool DeserializeHistogramInfo(const std::string& histogram_info); 394 static bool DeserializeHistogramInfo(const std::string& histogram_info);
369 395
396 // Check to see if bucket ranges, counts and tallies in the snapshot are
397 // consistent with the bucket ranges and checksums in our histogram. This can
398 // produce a false-alarm if a race occurred in the reading of the data during
399 // a SnapShot process, but should otherwise be false at all times (unless we
400 // have memory over-writes, or DRAM failures).
401 Inconsistencies FindCorruption(const SampleSet& snapshot) const;
402
370 //---------------------------------------------------------------------------- 403 //----------------------------------------------------------------------------
371 // Accessors for factory constuction, serialization and testing. 404 // Accessors for factory constuction, serialization and testing.
372 //---------------------------------------------------------------------------- 405 //----------------------------------------------------------------------------
373 virtual ClassType histogram_type() const { return HISTOGRAM; } 406 virtual ClassType histogram_type() const { return HISTOGRAM; }
374 const std::string& histogram_name() const { return histogram_name_; } 407 const std::string& histogram_name() const { return histogram_name_; }
375 Sample declared_min() const { return declared_min_; } 408 Sample declared_min() const { return declared_min_; }
376 Sample declared_max() const { return declared_max_; } 409 Sample declared_max() const { return declared_max_; }
377 virtual Sample ranges(size_t i) const { return ranges_[i];} 410 virtual Sample ranges(size_t i) const { return ranges_[i];}
411 Sample range_checksum() const { return range_checksum_; }
378 virtual size_t bucket_count() const { return bucket_count_; } 412 virtual size_t bucket_count() const { return bucket_count_; }
379 // Snapshot the current complete set of sample data. 413 // Snapshot the current complete set of sample data.
380 // Override with atomic/locked snapshot if needed. 414 // Override with atomic/locked snapshot if needed.
381 virtual void SnapshotSample(SampleSet* sample) const; 415 virtual void SnapshotSample(SampleSet* sample) const;
382 416
383 virtual bool HasConstructorArguments(Sample minimum, Sample maximum, 417 virtual bool HasConstructorArguments(Sample minimum, Sample maximum,
384 size_t bucket_count); 418 size_t bucket_count);
385 419
386 virtual bool HasConstructorTimeDeltaArguments(TimeDelta minimum, 420 virtual bool HasConstructorTimeDeltaArguments(TimeDelta minimum,
387 TimeDelta maximum, 421 TimeDelta maximum,
(...skipping 14 matching lines...) Expand all
402 //---------------------------------------------------------------------------- 436 //----------------------------------------------------------------------------
403 // Methods to override to create histogram with different bucket widths. 437 // Methods to override to create histogram with different bucket widths.
404 //---------------------------------------------------------------------------- 438 //----------------------------------------------------------------------------
405 // Initialize ranges_ mapping. 439 // Initialize ranges_ mapping.
406 virtual void InitializeBucketRange(); 440 virtual void InitializeBucketRange();
407 // Find bucket to increment for sample value. 441 // Find bucket to increment for sample value.
408 virtual size_t BucketIndex(Sample value) const; 442 virtual size_t BucketIndex(Sample value) const;
409 // Get normalized size, relative to the ranges_[i]. 443 // Get normalized size, relative to the ranges_[i].
410 virtual double GetBucketSize(Count current, size_t i) const; 444 virtual double GetBucketSize(Count current, size_t i) const;
411 445
446 // Recalculate range_checksum_.
447 void ResetRangeChecksum();
448
412 // Return a string description of what goes in a given bucket. 449 // Return a string description of what goes in a given bucket.
413 // Most commonly this is the numeric value, but in derived classes it may 450 // Most commonly this is the numeric value, but in derived classes it may
414 // be a name (or string description) given to the bucket. 451 // be a name (or string description) given to the bucket.
415 virtual const std::string GetAsciiBucketRange(size_t it) const; 452 virtual const std::string GetAsciiBucketRange(size_t it) const;
416 453
417 //---------------------------------------------------------------------------- 454 //----------------------------------------------------------------------------
418 // Methods to override to create thread safe histogram. 455 // Methods to override to create thread safe histogram.
419 //---------------------------------------------------------------------------- 456 //----------------------------------------------------------------------------
420 // Update all our internal data, including histogram 457 // Update all our internal data, including histogram
421 virtual void Accumulate(Sample value, Count count, size_t index); 458 virtual void Accumulate(Sample value, Count count, size_t index);
422 459
423 //---------------------------------------------------------------------------- 460 //----------------------------------------------------------------------------
424 // Accessors for derived classes. 461 // Accessors for derived classes.
425 //---------------------------------------------------------------------------- 462 //----------------------------------------------------------------------------
426 void SetBucketRange(size_t i, Sample value); 463 void SetBucketRange(size_t i, Sample value);
427 464
428 // Validate that ranges_ was created sensibly (top and bottom range 465 // Validate that ranges_ was created sensibly (top and bottom range
429 // values relate properly to the declared_min_ and declared_max_).. 466 // values relate properly to the declared_min_ and declared_max_)..
430 bool ValidateBucketRanges() const; 467 bool ValidateBucketRanges() const;
431 468
432 private: 469 private:
470 // Allow tests to corrupt our innards for testing purposes.
471 FRIEND_TEST(HistogramTest, CorruptBucketBounds);
472 FRIEND_TEST(HistogramTest, CorruptSampleCounts);
473
433 // Post constructor initialization. 474 // Post constructor initialization.
434 void Initialize(); 475 void Initialize();
435 476
477 // Return true iff the range_checksum_ matches current ranges_ vector.
478 bool HasValidRangeChecksum() const;
479
480 Sample CalculateRangeChecksum() const;
481
436 //---------------------------------------------------------------------------- 482 //----------------------------------------------------------------------------
437 // Helpers for emitting Ascii graphic. Each method appends data to output. 483 // Helpers for emitting Ascii graphic. Each method appends data to output.
438 484
439 // Find out how large the (graphically) the largest bucket will appear to be. 485 // Find out how large the (graphically) the largest bucket will appear to be.
440 double GetPeakBucketSize(const SampleSet& snapshot) const; 486 double GetPeakBucketSize(const SampleSet& snapshot) const;
441 487
442 // Write a common header message describing this histogram. 488 // Write a common header message describing this histogram.
443 void WriteAsciiHeader(const SampleSet& snapshot, 489 void WriteAsciiHeader(const SampleSet& snapshot,
444 Count sample_count, std::string* output) const; 490 Count sample_count, std::string* output) const;
445 491
(...skipping 24 matching lines...) Expand all
470 516
471 // Flag the histogram for recording by UMA via metric_services.h. 517 // Flag the histogram for recording by UMA via metric_services.h.
472 Flags flags_; 518 Flags flags_;
473 519
474 // For each index, show the least value that can be stored in the 520 // For each index, show the least value that can be stored in the
475 // corresponding bucket. We also append one extra element in this array, 521 // corresponding bucket. We also append one extra element in this array,
476 // containing kSampleType_MAX, to make calculations easy. 522 // containing kSampleType_MAX, to make calculations easy.
477 // The dimension of ranges_ is bucket_count + 1. 523 // The dimension of ranges_ is bucket_count + 1.
478 Ranges ranges_; 524 Ranges ranges_;
479 525
526 // For redundancy, we store the sum of all the sample ranges when ranges are
527 // generated. If ever there is ever a difference, then the histogram must
528 // have been corrupted.
529 Sample range_checksum_;
530
480 // Finally, provide the state that changes with the addition of each new 531 // Finally, provide the state that changes with the addition of each new
481 // sample. 532 // sample.
482 SampleSet sample_; 533 SampleSet sample_;
483 534
484 DISALLOW_COPY_AND_ASSIGN(Histogram); 535 DISALLOW_COPY_AND_ASSIGN(Histogram);
485 }; 536 };
486 537
487 //------------------------------------------------------------------------------ 538 //------------------------------------------------------------------------------
488 539
489 // LinearHistogram is a more traditional histogram, with evenly spaced 540 // LinearHistogram is a more traditional histogram, with evenly spaced
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 }; 605 };
555 606
556 //------------------------------------------------------------------------------ 607 //------------------------------------------------------------------------------
557 608
558 // CustomHistogram is a histogram for a set of custom integers. 609 // CustomHistogram is a histogram for a set of custom integers.
559 class CustomHistogram : public Histogram { 610 class CustomHistogram : public Histogram {
560 public: 611 public:
561 virtual ClassType histogram_type() const; 612 virtual ClassType histogram_type() const;
562 613
563 static scoped_refptr<Histogram> FactoryGet(const std::string& name, 614 static scoped_refptr<Histogram> FactoryGet(const std::string& name,
564 const std::vector<int>& custom_ranges, Flags flags); 615 const std::vector<Sample>& custom_ranges, Flags flags);
565 616
566 protected: 617 protected:
567 CustomHistogram(const std::string& name, 618 CustomHistogram(const std::string& name,
568 const std::vector<int>& custom_ranges); 619 const std::vector<Sample>& custom_ranges);
569 620
570 // Initialize ranges_ mapping. 621 // Initialize ranges_ mapping.
571 virtual void InitializeBucketRange(); 622 virtual void InitializeBucketRange();
572 virtual double GetBucketSize(Count current, size_t i) const; 623 virtual double GetBucketSize(Count current, size_t i) const;
573 624
574 private: 625 private:
575 // Temporary pointer used during construction/initialization, and then NULLed. 626 // Temporary pointer used during construction/initialization, and then NULLed.
576 const std::vector<int>* ranges_vector_; 627 const std::vector<Sample>* ranges_vector_;
577 628
578 DISALLOW_COPY_AND_ASSIGN(CustomHistogram); 629 DISALLOW_COPY_AND_ASSIGN(CustomHistogram);
579 }; 630 };
580 631
581 //------------------------------------------------------------------------------ 632 //------------------------------------------------------------------------------
582 // StatisticsRecorder handles all histograms in the system. It provides a 633 // StatisticsRecorder handles all histograms in the system. It provides a
583 // general place for histograms to register, and supports a global API for 634 // general place for histograms to register, and supports a global API for
584 // accessing (i.e., dumping, or graphing) the data in all the histograms. 635 // accessing (i.e., dumping, or graphing) the data in all the histograms.
585 636
586 class StatisticsRecorder { 637 class StatisticsRecorder {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 685
635 // Dump all known histograms to log. 686 // Dump all known histograms to log.
636 static bool dump_on_exit_; 687 static bool dump_on_exit_;
637 688
638 DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder); 689 DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder);
639 }; 690 };
640 691
641 } // namespace base 692 } // namespace base
642 693
643 #endif // BASE_METRICS_HISTOGRAM_H_ 694 #endif // BASE_METRICS_HISTOGRAM_H_
OLDNEW
« no previous file with comments | « no previous file | base/metrics/histogram.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698