| 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 |