OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/histogram.h" | 10 #include "base/histogram.h" |
11 | 11 |
12 #include <math.h> | 12 #include <math.h> |
13 #include <string> | 13 #include <string> |
14 | 14 |
15 #include "base/logging.h" | 15 #include "base/logging.h" |
16 #include "base/pickle.h" | 16 #include "base/pickle.h" |
17 #include "base/string_util.h" | 17 #include "base/string_util.h" |
18 | 18 |
19 using base::TimeDelta; | 19 using base::TimeDelta; |
20 | 20 |
21 typedef Histogram::Count Count; | 21 typedef Histogram::Count Count; |
22 | 22 |
23 // static | 23 // static |
24 const int Histogram::kHexRangePrintingFlag = 0x8000; | 24 const int Histogram::kHexRangePrintingFlag = 0x8000; |
25 | 25 |
26 Histogram::Histogram(const char* name, Sample minimum, | 26 scoped_refptr<Histogram> Histogram::HistogramFactoryGet( |
| 27 const std::string& name, Sample minimum, Sample maximum, |
| 28 size_t bucket_count) { |
| 29 scoped_refptr<Histogram> histogram(NULL); |
| 30 |
| 31 // Defensive code. |
| 32 if (minimum <= 0) |
| 33 minimum = 1; |
| 34 if (maximum >= kSampleType_MAX) |
| 35 maximum = kSampleType_MAX - 1; |
| 36 |
| 37 if (StatisticsRecorder::FindHistogram(name, &histogram)) { |
| 38 DCHECK(histogram.get() != NULL); |
| 39 } else { |
| 40 histogram = new Histogram(name, minimum, maximum, bucket_count); |
| 41 scoped_refptr<Histogram> registered_histogram(NULL); |
| 42 StatisticsRecorder::FindHistogram(name, ®istered_histogram); |
| 43 // Allow a NULL return to mean that the StatisticsRecorder was not started. |
| 44 if (registered_histogram.get() != NULL && |
| 45 registered_histogram.get() != histogram.get()) |
| 46 histogram = registered_histogram; |
| 47 } |
| 48 |
| 49 DCHECK(HISTOGRAM == histogram->histogram_type()); |
| 50 DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count)); |
| 51 return histogram; |
| 52 } |
| 53 |
| 54 scoped_refptr<Histogram> Histogram::HistogramFactoryGet( |
| 55 const std::string& name, base::TimeDelta minimum, base::TimeDelta maximum, |
| 56 size_t bucket_count) { |
| 57 return HistogramFactoryGet(name, |
| 58 minimum.InMilliseconds(), maximum.InMilliseconds(), bucket_count); |
| 59 } |
| 60 |
| 61 Histogram::Histogram(const std::string& name, Sample minimum, |
27 Sample maximum, size_t bucket_count) | 62 Sample maximum, size_t bucket_count) |
28 : histogram_name_(name), | 63 : histogram_name_(name), |
29 declared_min_(minimum), | 64 declared_min_(minimum), |
30 declared_max_(maximum), | 65 declared_max_(maximum), |
31 bucket_count_(bucket_count), | 66 bucket_count_(bucket_count), |
32 flags_(0), | 67 flags_(0), |
33 ranges_(bucket_count + 1, 0), | 68 ranges_(bucket_count + 1, 0), |
34 sample_(), | 69 sample_() { |
35 registered_(false) { | |
36 Initialize(); | 70 Initialize(); |
37 } | 71 } |
38 | 72 |
39 Histogram::Histogram(const char* name, TimeDelta minimum, | 73 Histogram::Histogram(const std::string& name, TimeDelta minimum, |
40 TimeDelta maximum, size_t bucket_count) | 74 TimeDelta maximum, size_t bucket_count) |
41 : histogram_name_(name), | 75 : histogram_name_(name), |
42 declared_min_(static_cast<int> (minimum.InMilliseconds())), | 76 declared_min_(static_cast<int> (minimum.InMilliseconds())), |
43 declared_max_(static_cast<int> (maximum.InMilliseconds())), | 77 declared_max_(static_cast<int> (maximum.InMilliseconds())), |
44 bucket_count_(bucket_count), | 78 bucket_count_(bucket_count), |
45 flags_(0), | 79 flags_(0), |
46 ranges_(bucket_count + 1, 0), | 80 ranges_(bucket_count + 1, 0), |
47 sample_(), | 81 sample_() { |
48 registered_(false) { | |
49 Initialize(); | 82 Initialize(); |
50 } | 83 } |
51 | 84 |
52 Histogram::~Histogram() { | 85 Histogram::~Histogram() { |
53 if (registered_) | 86 DCHECK(!(kPlannedLeakFlag & flags_)); |
54 StatisticsRecorder::UnRegister(this); | 87 if (StatisticsRecorder::dump_on_exit()) { |
| 88 std::string output; |
| 89 WriteAscii(true, "\n", &output); |
| 90 LOG(INFO) << output; |
| 91 } |
| 92 |
55 // Just to make sure most derived class did this properly... | 93 // Just to make sure most derived class did this properly... |
56 DCHECK(ValidateBucketRanges()); | 94 DCHECK(ValidateBucketRanges()); |
57 } | 95 } |
58 | 96 |
59 void Histogram::Add(int value) { | 97 void Histogram::Add(int value) { |
60 if (!registered_) | |
61 registered_ = StatisticsRecorder::Register(this); | |
62 if (value >= kSampleType_MAX) | 98 if (value >= kSampleType_MAX) |
63 value = kSampleType_MAX - 1; | 99 value = kSampleType_MAX - 1; |
64 if (value < 0) | 100 if (value < 0) |
65 value = 0; | 101 value = 0; |
66 size_t index = BucketIndex(value); | 102 size_t index = BucketIndex(value); |
67 DCHECK(value >= ranges(index)); | 103 DCHECK(value >= ranges(index)); |
68 DCHECK(value < ranges(index + 1)); | 104 DCHECK(value < ranges(index + 1)); |
69 Accumulate(value, 1, index); | 105 Accumulate(value, 1, index); |
70 } | 106 } |
71 | 107 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 declared_max_ = kSampleType_MAX - 1; | 199 declared_max_ = kSampleType_MAX - 1; |
164 DCHECK(declared_min_ > 0); // We provide underflow bucket. | 200 DCHECK(declared_min_ > 0); // We provide underflow bucket. |
165 DCHECK(declared_min_ <= declared_max_); | 201 DCHECK(declared_min_ <= declared_max_); |
166 DCHECK(1 < bucket_count_); | 202 DCHECK(1 < bucket_count_); |
167 size_t maximal_bucket_count = declared_max_ - declared_min_ + 2; | 203 size_t maximal_bucket_count = declared_max_ - declared_min_ + 2; |
168 DCHECK(bucket_count_ <= maximal_bucket_count); | 204 DCHECK(bucket_count_ <= maximal_bucket_count); |
169 DCHECK(0 == ranges_[0]); | 205 DCHECK(0 == ranges_[0]); |
170 ranges_[bucket_count_] = kSampleType_MAX; | 206 ranges_[bucket_count_] = kSampleType_MAX; |
171 InitializeBucketRange(); | 207 InitializeBucketRange(); |
172 DCHECK(ValidateBucketRanges()); | 208 DCHECK(ValidateBucketRanges()); |
173 registered_ = StatisticsRecorder::Register(this); | 209 StatisticsRecorder::Register(this); |
174 } | 210 } |
175 | 211 |
176 // Calculate what range of values are held in each bucket. | 212 // Calculate what range of values are held in each bucket. |
177 // We have to be careful that we don't pick a ratio between starting points in | 213 // We have to be careful that we don't pick a ratio between starting points in |
178 // consecutive buckets that is sooo small, that the integer bounds are the same | 214 // consecutive buckets that is sooo small, that the integer bounds are the same |
179 // (effectively making one bucket get no values). We need to avoid: | 215 // (effectively making one bucket get no values). We need to avoid: |
180 // (ranges_[i] == ranges_[i + 1] | 216 // (ranges_[i] == ranges_[i + 1] |
181 // To avoid that, we just do a fine-grained bucket width as far as we need to | 217 // To avoid that, we just do a fine-grained bucket width as far as we need to |
182 // until we get a ratio that moves us along at least 2 units at a time. From | 218 // until we get a ratio that moves us along at least 2 units at a time. From |
183 // that bucket onward we do use the exponential growth of buckets. | 219 // that bucket onward we do use the exponential growth of buckets. |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 while (0 < x_count--) | 382 while (0 < x_count--) |
347 output->append("-"); | 383 output->append("-"); |
348 output->append("O"); | 384 output->append("O"); |
349 while (0 < x_remainder--) | 385 while (0 < x_remainder--) |
350 output->append(" "); | 386 output->append(" "); |
351 } | 387 } |
352 | 388 |
353 // static | 389 // static |
354 std::string Histogram::SerializeHistogramInfo(const Histogram& histogram, | 390 std::string Histogram::SerializeHistogramInfo(const Histogram& histogram, |
355 const SampleSet& snapshot) { | 391 const SampleSet& snapshot) { |
| 392 DCHECK(histogram.histogram_type() != NOT_VALID_IN_RENDERER); |
| 393 |
356 Pickle pickle; | 394 Pickle pickle; |
357 | |
358 pickle.WriteString(histogram.histogram_name()); | 395 pickle.WriteString(histogram.histogram_name()); |
359 pickle.WriteInt(histogram.declared_min()); | 396 pickle.WriteInt(histogram.declared_min()); |
360 pickle.WriteInt(histogram.declared_max()); | 397 pickle.WriteInt(histogram.declared_max()); |
361 pickle.WriteSize(histogram.bucket_count()); | 398 pickle.WriteSize(histogram.bucket_count()); |
362 pickle.WriteInt(histogram.histogram_type()); | 399 pickle.WriteInt(histogram.histogram_type()); |
363 pickle.WriteInt(histogram.flags()); | 400 pickle.WriteInt(histogram.flags() & ~kIPCSerializationSourceFlag); |
364 | 401 |
365 snapshot.Serialize(&pickle); | 402 snapshot.Serialize(&pickle); |
366 return std::string(static_cast<const char*>(pickle.data()), pickle.size()); | 403 return std::string(static_cast<const char*>(pickle.data()), pickle.size()); |
367 } | 404 } |
368 | 405 |
369 // static | 406 // static |
370 bool Histogram::DeserializeHistogramInfo(const std::string& histogram_info) { | 407 bool Histogram::DeserializeHistogramInfo(const std::string& histogram_info) { |
371 if (histogram_info.empty()) { | 408 if (histogram_info.empty()) { |
372 return false; | 409 return false; |
373 } | 410 } |
(...skipping 13 matching lines...) Expand all Loading... |
387 !pickle.ReadInt(&iter, &declared_min) || | 424 !pickle.ReadInt(&iter, &declared_min) || |
388 !pickle.ReadInt(&iter, &declared_max) || | 425 !pickle.ReadInt(&iter, &declared_max) || |
389 !pickle.ReadSize(&iter, &bucket_count) || | 426 !pickle.ReadSize(&iter, &bucket_count) || |
390 !pickle.ReadInt(&iter, &histogram_type) || | 427 !pickle.ReadInt(&iter, &histogram_type) || |
391 !pickle.ReadInt(&iter, &flags) || | 428 !pickle.ReadInt(&iter, &flags) || |
392 !sample.Histogram::SampleSet::Deserialize(&iter, pickle)) { | 429 !sample.Histogram::SampleSet::Deserialize(&iter, pickle)) { |
393 LOG(ERROR) << "Picke error decoding Histogram: " << histogram_name; | 430 LOG(ERROR) << "Picke error decoding Histogram: " << histogram_name; |
394 return false; | 431 return false; |
395 } | 432 } |
396 | 433 |
397 Histogram* render_histogram = | 434 DCHECK(histogram_type != NOT_VALID_IN_RENDERER); |
398 StatisticsRecorder::GetHistogram(histogram_name); | |
399 | 435 |
400 if (render_histogram == NULL) { | 436 scoped_refptr<Histogram> render_histogram(NULL); |
401 if (histogram_type == EXPONENTIAL) { | 437 |
402 render_histogram = new Histogram(histogram_name.c_str(), | 438 if (histogram_type == HISTOGRAM) { |
403 declared_min, | 439 render_histogram = Histogram::HistogramFactoryGet( |
404 declared_max, | 440 histogram_name, declared_min, declared_max, bucket_count); |
405 bucket_count); | 441 } else if (histogram_type == LINEAR_HISTOGRAM) { |
406 } else if (histogram_type == LINEAR) { | 442 render_histogram = LinearHistogram::LinearHistogramFactoryGet( |
407 render_histogram = new LinearHistogram(histogram_name.c_str(), | 443 histogram_name, declared_min, declared_max, bucket_count); |
408 declared_min, | 444 } else if (histogram_type == BOOLEAN_HISTOGRAM) { |
409 declared_max, | 445 render_histogram = BooleanHistogram::BooleanHistogramFactoryGet( |
410 bucket_count); | 446 histogram_name); |
411 } else { | 447 } else if (histogram_type == THREAD_SAFE_HISTOGRAM) { |
412 LOG(ERROR) << "Error Deserializing Histogram Unknown histogram_type: " << | 448 render_histogram = |
413 histogram_type; | 449 ThreadSafeHistogram::ThreadSafeHistogramFactoryGet( |
414 return false; | 450 histogram_name, declared_min, declared_max, bucket_count); |
415 } | 451 } else { |
416 DCHECK(!(flags & kRendererHistogramFlag)); | 452 LOG(ERROR) << "Error Deserializing Histogram Unknown histogram_type: " << |
417 render_histogram->SetFlags(flags | kRendererHistogramFlag); | 453 histogram_type; |
| 454 return false; |
418 } | 455 } |
419 | 456 |
420 DCHECK(declared_min == render_histogram->declared_min()); | 457 DCHECK(declared_min == render_histogram->declared_min()); |
421 DCHECK(declared_max == render_histogram->declared_max()); | 458 DCHECK(declared_max == render_histogram->declared_max()); |
422 DCHECK(bucket_count == render_histogram->bucket_count()); | 459 DCHECK(bucket_count == render_histogram->bucket_count()); |
423 DCHECK(histogram_type == render_histogram->histogram_type()); | 460 DCHECK(histogram_type == render_histogram->histogram_type()); |
424 | 461 |
425 if (render_histogram->flags() & kRendererHistogramFlag) { | 462 if (render_histogram->flags() & kIPCSerializationSourceFlag) { |
| 463 DLOG(INFO) << "Single process mode, histogram observed and not copied: " << |
| 464 histogram_name; |
| 465 } else { |
426 render_histogram->AddSampleSet(sample); | 466 render_histogram->AddSampleSet(sample); |
427 } else { | |
428 DLOG(INFO) << "Single thread mode, histogram observed and not copied: " << | |
429 histogram_name; | |
430 } | 467 } |
431 | 468 |
432 return true; | 469 return true; |
433 } | 470 } |
434 | 471 |
435 | |
436 //------------------------------------------------------------------------------ | 472 //------------------------------------------------------------------------------ |
437 // Methods for the Histogram::SampleSet class | 473 // Methods for the Histogram::SampleSet class |
438 //------------------------------------------------------------------------------ | 474 //------------------------------------------------------------------------------ |
439 | 475 |
440 Histogram::SampleSet::SampleSet() | 476 Histogram::SampleSet::SampleSet() |
441 : counts_(), | 477 : counts_(), |
442 sum_(0), | 478 sum_(0), |
443 square_sum_(0) { | 479 square_sum_(0) { |
444 } | 480 } |
445 | 481 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
530 } | 566 } |
531 | 567 |
532 return true; | 568 return true; |
533 } | 569 } |
534 | 570 |
535 //------------------------------------------------------------------------------ | 571 //------------------------------------------------------------------------------ |
536 // LinearHistogram: This histogram uses a traditional set of evenly spaced | 572 // LinearHistogram: This histogram uses a traditional set of evenly spaced |
537 // buckets. | 573 // buckets. |
538 //------------------------------------------------------------------------------ | 574 //------------------------------------------------------------------------------ |
539 | 575 |
540 LinearHistogram::LinearHistogram(const char* name, Sample minimum, | 576 scoped_refptr<Histogram> LinearHistogram::LinearHistogramFactoryGet( |
| 577 const std::string& name, Sample minimum, Sample maximum, |
| 578 size_t bucket_count) { |
| 579 scoped_refptr<Histogram> histogram(NULL); |
| 580 |
| 581 if (minimum <= 0) |
| 582 minimum = 1; |
| 583 if (maximum >= kSampleType_MAX) |
| 584 maximum = kSampleType_MAX - 1; |
| 585 |
| 586 if (StatisticsRecorder::FindHistogram(name, &histogram)) { |
| 587 DCHECK(histogram.get() != NULL); |
| 588 } else { |
| 589 histogram = new LinearHistogram(name, minimum, maximum, bucket_count); |
| 590 scoped_refptr<Histogram> registered_histogram(NULL); |
| 591 StatisticsRecorder::FindHistogram(name, ®istered_histogram); |
| 592 if (registered_histogram.get() != NULL && |
| 593 registered_histogram.get() != histogram.get()) |
| 594 histogram = registered_histogram; |
| 595 } |
| 596 |
| 597 DCHECK(LINEAR_HISTOGRAM == histogram->histogram_type()); |
| 598 DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count)); |
| 599 |
| 600 return histogram; |
| 601 } |
| 602 |
| 603 scoped_refptr<Histogram> LinearHistogram::LinearHistogramFactoryGet( |
| 604 const std::string& name, base::TimeDelta minimum, base::TimeDelta maximum, |
| 605 size_t bucket_count) { |
| 606 return LinearHistogramFactoryGet(name, minimum.InMilliseconds(), |
| 607 maximum.InMilliseconds(), bucket_count); |
| 608 } |
| 609 |
| 610 LinearHistogram::LinearHistogram(const std::string& name, Sample minimum, |
541 Sample maximum, size_t bucket_count) | 611 Sample maximum, size_t bucket_count) |
542 : Histogram(name, minimum >= 1 ? minimum : 1, maximum, bucket_count) { | 612 : Histogram(name, minimum >= 1 ? minimum : 1, maximum, bucket_count) { |
543 InitializeBucketRange(); | 613 InitializeBucketRange(); |
544 DCHECK(ValidateBucketRanges()); | 614 DCHECK(ValidateBucketRanges()); |
545 } | 615 } |
546 | 616 |
547 LinearHistogram::LinearHistogram(const char* name, | 617 LinearHistogram::LinearHistogram(const std::string& name, |
548 TimeDelta minimum, TimeDelta maximum, size_t bucket_count) | 618 TimeDelta minimum, TimeDelta maximum, size_t bucket_count) |
549 : Histogram(name, minimum >= TimeDelta::FromMilliseconds(1) ? | 619 : Histogram(name, minimum >= TimeDelta::FromMilliseconds(1) ? |
550 minimum : TimeDelta::FromMilliseconds(1), | 620 minimum : TimeDelta::FromMilliseconds(1), |
551 maximum, bucket_count) { | 621 maximum, bucket_count) { |
552 // Do a "better" (different) job at init than a base classes did... | 622 // Do a "better" (different) job at init than a base classes did... |
553 InitializeBucketRange(); | 623 InitializeBucketRange(); |
554 DCHECK(ValidateBucketRanges()); | 624 DCHECK(ValidateBucketRanges()); |
555 } | 625 } |
556 | 626 |
557 void LinearHistogram::SetRangeDescriptions( | 627 void LinearHistogram::SetRangeDescriptions( |
(...skipping 30 matching lines...) Expand all Loading... |
588 | 658 |
589 double LinearHistogram::GetBucketSize(Count current, size_t i) const { | 659 double LinearHistogram::GetBucketSize(Count current, size_t i) const { |
590 DCHECK(ranges(i + 1) > ranges(i)); | 660 DCHECK(ranges(i + 1) > ranges(i)); |
591 // Adjacent buckets with different widths would have "surprisingly" many (few) | 661 // Adjacent buckets with different widths would have "surprisingly" many (few) |
592 // samples in a histogram if we didn't normalize this way. | 662 // samples in a histogram if we didn't normalize this way. |
593 double denominator = ranges(i + 1) - ranges(i); | 663 double denominator = ranges(i + 1) - ranges(i); |
594 return current/denominator; | 664 return current/denominator; |
595 } | 665 } |
596 | 666 |
597 //------------------------------------------------------------------------------ | 667 //------------------------------------------------------------------------------ |
| 668 // This section provides implementation for BooleanHistogram. |
| 669 //------------------------------------------------------------------------------ |
| 670 |
| 671 scoped_refptr<Histogram> BooleanHistogram::BooleanHistogramFactoryGet( |
| 672 const std::string& name) { |
| 673 scoped_refptr<Histogram> histogram(NULL); |
| 674 |
| 675 if (StatisticsRecorder::FindHistogram(name, &histogram)) { |
| 676 DCHECK(histogram.get() != NULL); |
| 677 } else { |
| 678 histogram = new BooleanHistogram(name); |
| 679 scoped_refptr<Histogram> registered_histogram(NULL); |
| 680 StatisticsRecorder::FindHistogram(name, ®istered_histogram); |
| 681 if (registered_histogram.get() != NULL && |
| 682 registered_histogram.get() != histogram.get()) |
| 683 histogram = registered_histogram; |
| 684 } |
| 685 |
| 686 DCHECK(BOOLEAN_HISTOGRAM == histogram->histogram_type()); |
| 687 |
| 688 return histogram; |
| 689 } |
| 690 |
| 691 //------------------------------------------------------------------------------ |
598 // This section provides implementation for ThreadSafeHistogram. | 692 // This section provides implementation for ThreadSafeHistogram. |
599 //------------------------------------------------------------------------------ | 693 //------------------------------------------------------------------------------ |
600 | 694 |
601 ThreadSafeHistogram::ThreadSafeHistogram(const char* name, Sample minimum, | 695 scoped_refptr<Histogram> ThreadSafeHistogram::ThreadSafeHistogramFactoryGet( |
602 Sample maximum, size_t bucket_count) | 696 const std::string& name, Sample minimum, Sample maximum, |
| 697 size_t bucket_count) { |
| 698 scoped_refptr<Histogram> histogram(NULL); |
| 699 |
| 700 if (minimum <= 0) |
| 701 minimum = 1; |
| 702 if (maximum >= kSampleType_MAX) |
| 703 maximum = kSampleType_MAX - 1; |
| 704 |
| 705 if (StatisticsRecorder::FindHistogram(name, &histogram)) { |
| 706 DCHECK(histogram.get() != NULL); |
| 707 } else { |
| 708 histogram = new ThreadSafeHistogram(name, minimum, maximum, bucket_count); |
| 709 scoped_refptr<Histogram> registered_histogram(NULL); |
| 710 StatisticsRecorder::FindHistogram(name, ®istered_histogram); |
| 711 if (registered_histogram.get() != NULL && |
| 712 registered_histogram.get() != histogram.get()) |
| 713 histogram = registered_histogram; |
| 714 } |
| 715 |
| 716 DCHECK(THREAD_SAFE_HISTOGRAM == histogram->histogram_type()); |
| 717 DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count)); |
| 718 return histogram; |
| 719 } |
| 720 |
| 721 ThreadSafeHistogram::ThreadSafeHistogram(const std::string& name, |
| 722 Sample minimum, Sample maximum, size_t bucket_count) |
603 : Histogram(name, minimum, maximum, bucket_count), | 723 : Histogram(name, minimum, maximum, bucket_count), |
604 lock_() { | 724 lock_() { |
605 } | 725 } |
606 | 726 |
607 void ThreadSafeHistogram::Remove(int value) { | 727 void ThreadSafeHistogram::Remove(int value) { |
608 if (value >= kSampleType_MAX) | 728 if (value >= kSampleType_MAX) |
609 value = kSampleType_MAX - 1; | 729 value = kSampleType_MAX - 1; |
610 size_t index = BucketIndex(value); | 730 size_t index = BucketIndex(value); |
611 Accumulate(value, -1, index); | 731 Accumulate(value, -1, index); |
612 } | 732 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
650 histograms_ = NULL; | 770 histograms_ = NULL; |
651 delete lock_; | 771 delete lock_; |
652 lock_ = NULL; | 772 lock_ = NULL; |
653 } | 773 } |
654 | 774 |
655 // static | 775 // static |
656 bool StatisticsRecorder::WasStarted() { | 776 bool StatisticsRecorder::WasStarted() { |
657 return NULL != histograms_; | 777 return NULL != histograms_; |
658 } | 778 } |
659 | 779 |
| 780 // Note: We can't accept a ref_ptr to |histogram| because we *might* not keep a |
| 781 // reference, and we are called while in the Histogram constructor. In that |
| 782 // scenario, a ref_ptr would have incremented the ref count when the histogram |
| 783 // was passed to us, decremented it when we returned, and the instance would be |
| 784 // destroyed before assignment (when value was returned by new). |
660 // static | 785 // static |
661 bool StatisticsRecorder::Register(Histogram* histogram) { | 786 void StatisticsRecorder::Register(Histogram* histogram) { |
662 if (!histograms_) | |
663 return false; | |
664 const std::string name = histogram->histogram_name(); | |
665 AutoLock auto_lock(*lock_); | |
666 | |
667 if (histograms_->end() != histograms_->find(name)) { | |
668 // Check to be sure it is compatible.... and if not, then do a CHECK() | |
669 return false; // This name is already registered. | |
670 } | |
671 (*histograms_)[name] = histogram; | |
672 return true; | |
673 } | |
674 | |
675 // static | |
676 void StatisticsRecorder::UnRegister(Histogram* histogram) { | |
677 if (!histograms_) | 787 if (!histograms_) |
678 return; | 788 return; |
679 const std::string name = histogram->histogram_name(); | 789 const std::string name = histogram->histogram_name(); |
680 AutoLock auto_lock(*lock_); | 790 AutoLock auto_lock(*lock_); |
681 DCHECK(histograms_->end() != histograms_->find(name)); | 791 |
682 histograms_->erase(name); | 792 DCHECK(histograms_->end() == histograms_->find(name)); |
683 if (dump_on_exit_) { | 793 |
684 std::string output; | 794 (*histograms_)[name] = histogram; |
685 histogram->WriteAscii(true, "\n", &output); | 795 return; |
686 LOG(INFO) << output; | |
687 } | |
688 } | 796 } |
689 | 797 |
690 // static | 798 // static |
691 void StatisticsRecorder::WriteHTMLGraph(const std::string& query, | 799 void StatisticsRecorder::WriteHTMLGraph(const std::string& query, |
692 std::string* output) { | 800 std::string* output) { |
693 if (!histograms_) | 801 if (!histograms_) |
694 return; | 802 return; |
695 output->append("<html><head><title>About Histograms"); | 803 output->append("<html><head><title>About Histograms"); |
696 if (!query.empty()) | 804 if (!query.empty()) |
697 output->append(" - " + query); | 805 output->append(" - " + query); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
736 if (!histograms_) | 844 if (!histograms_) |
737 return; | 845 return; |
738 AutoLock auto_lock(*lock_); | 846 AutoLock auto_lock(*lock_); |
739 for (HistogramMap::iterator it = histograms_->begin(); | 847 for (HistogramMap::iterator it = histograms_->begin(); |
740 histograms_->end() != it; | 848 histograms_->end() != it; |
741 ++it) { | 849 ++it) { |
742 output->push_back(it->second); | 850 output->push_back(it->second); |
743 } | 851 } |
744 } | 852 } |
745 | 853 |
746 Histogram* StatisticsRecorder::GetHistogram(const std::string& query) { | 854 // static |
| 855 void StatisticsRecorder::GetHistogramsForRenderer(Histograms* output) { |
747 if (!histograms_) | 856 if (!histograms_) |
748 return NULL; | 857 return; |
749 AutoLock auto_lock(*lock_); | 858 AutoLock auto_lock(*lock_); |
750 for (HistogramMap::iterator it = histograms_->begin(); | 859 for (HistogramMap::iterator it = histograms_->begin(); |
751 histograms_->end() != it; | 860 histograms_->end() != it; |
752 ++it) { | 861 ++it) { |
753 if (it->first.find(query) != std::string::npos) | 862 scoped_refptr<Histogram> histogram = it->second; |
754 return it->second; | 863 if (!(histogram->flags() & kIPCSerializationSourceFlag)) |
| 864 histogram->SetFlags(kIPCSerializationSourceFlag); |
| 865 output->push_back(histogram); |
755 } | 866 } |
756 return NULL; | 867 } |
| 868 |
| 869 bool StatisticsRecorder::FindHistogram(const std::string& name, |
| 870 scoped_refptr<Histogram>* histogram) { |
| 871 if (!histograms_) |
| 872 return false; |
| 873 AutoLock auto_lock(*lock_); |
| 874 HistogramMap::iterator it = histograms_->find(name); |
| 875 if (histograms_->end() == it) |
| 876 return false; |
| 877 *histogram = it->second; |
| 878 return true; |
757 } | 879 } |
758 | 880 |
759 // private static | 881 // private static |
760 void StatisticsRecorder::GetSnapshot(const std::string& query, | 882 void StatisticsRecorder::GetSnapshot(const std::string& query, |
761 Histograms* snapshot) { | 883 Histograms* snapshot) { |
762 AutoLock auto_lock(*lock_); | 884 AutoLock auto_lock(*lock_); |
763 for (HistogramMap::iterator it = histograms_->begin(); | 885 for (HistogramMap::iterator it = histograms_->begin(); |
764 histograms_->end() != it; | 886 histograms_->end() != it; |
765 ++it) { | 887 ++it) { |
766 if (it->first.find(query) != std::string::npos) | 888 if (it->first.find(query) != std::string::npos) |
767 snapshot->push_back(it->second); | 889 snapshot->push_back(it->second); |
768 } | 890 } |
769 } | 891 } |
770 | 892 |
771 // static | 893 // static |
772 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; | 894 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; |
773 // static | 895 // static |
774 Lock* StatisticsRecorder::lock_ = NULL; | 896 Lock* StatisticsRecorder::lock_ = NULL; |
775 // static | 897 // static |
776 bool StatisticsRecorder::dump_on_exit_ = false; | 898 bool StatisticsRecorder::dump_on_exit_ = false; |
OLD | NEW |