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

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

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