| 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 scoped_refptr<Histogram> Histogram::FactoryGet(const std::string& name, |
| 24 const int Histogram::kHexRangePrintingFlag = 0x8000; | 24 Sample minimum, Sample maximum, size_t bucket_count, Flags flags) { |
| 25 | |
| 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); | 25 scoped_refptr<Histogram> histogram(NULL); |
| 30 | 26 |
| 31 // Defensive code. | 27 // Defensive code. |
| 32 if (minimum <= 0) | 28 if (minimum <= 0) |
| 33 minimum = 1; | 29 minimum = 1; |
| 34 if (maximum >= kSampleType_MAX) | 30 if (maximum >= kSampleType_MAX) |
| 35 maximum = kSampleType_MAX - 1; | 31 maximum = kSampleType_MAX - 1; |
| 36 | 32 |
| 37 if (StatisticsRecorder::FindHistogram(name, &histogram)) { | 33 if (StatisticsRecorder::FindHistogram(name, &histogram)) { |
| 38 DCHECK(histogram.get() != NULL); | 34 DCHECK(histogram.get() != NULL); |
| 39 } else { | 35 } else { |
| 40 histogram = new Histogram(name, minimum, maximum, bucket_count); | 36 histogram = new Histogram(name, minimum, maximum, bucket_count); |
| 41 scoped_refptr<Histogram> registered_histogram(NULL); | 37 scoped_refptr<Histogram> registered_histogram(NULL); |
| 42 StatisticsRecorder::FindHistogram(name, ®istered_histogram); | 38 StatisticsRecorder::FindHistogram(name, ®istered_histogram); |
| 43 // Allow a NULL return to mean that the StatisticsRecorder was not started. | 39 // Allow a NULL return to mean that the StatisticsRecorder was not started. |
| 44 if (registered_histogram.get() != NULL && | 40 if (registered_histogram.get() != NULL && |
| 45 registered_histogram.get() != histogram.get()) | 41 registered_histogram.get() != histogram.get()) |
| 46 histogram = registered_histogram; | 42 histogram = registered_histogram; |
| 47 } | 43 } |
| 48 | 44 |
| 49 DCHECK(HISTOGRAM == histogram->histogram_type()); | 45 DCHECK(HISTOGRAM == histogram->histogram_type()); |
| 50 DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count)); | 46 DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count)); |
| 47 histogram->SetFlags(flags); |
| 51 return histogram; | 48 return histogram; |
| 52 } | 49 } |
| 53 | 50 |
| 54 scoped_refptr<Histogram> Histogram::HistogramFactoryGet( | 51 scoped_refptr<Histogram> Histogram::FactoryGet(const std::string& name, |
| 55 const std::string& name, base::TimeDelta minimum, base::TimeDelta maximum, | 52 base::TimeDelta minimum, base::TimeDelta maximum, size_t bucket_count, |
| 56 size_t bucket_count) { | 53 Flags flags) { |
| 57 return HistogramFactoryGet(name, | 54 return FactoryGet(name, minimum.InMilliseconds(), maximum.InMilliseconds(), |
| 58 minimum.InMilliseconds(), maximum.InMilliseconds(), bucket_count); | 55 bucket_count, flags); |
| 59 } | 56 } |
| 60 | 57 |
| 61 Histogram::Histogram(const std::string& name, Sample minimum, | 58 Histogram::Histogram(const std::string& name, Sample minimum, |
| 62 Sample maximum, size_t bucket_count) | 59 Sample maximum, size_t bucket_count) |
| 63 : histogram_name_(name), | 60 : histogram_name_(name), |
| 64 declared_min_(minimum), | 61 declared_min_(minimum), |
| 65 declared_max_(maximum), | 62 declared_max_(maximum), |
| 66 bucket_count_(bucket_count), | 63 bucket_count_(bucket_count), |
| 67 flags_(0), | 64 flags_(kNoFlags), |
| 68 ranges_(bucket_count + 1, 0), | 65 ranges_(bucket_count + 1, 0), |
| 69 sample_() { | 66 sample_() { |
| 70 Initialize(); | 67 Initialize(); |
| 71 } | 68 } |
| 72 | 69 |
| 73 Histogram::Histogram(const std::string& name, TimeDelta minimum, | 70 Histogram::Histogram(const std::string& name, TimeDelta minimum, |
| 74 TimeDelta maximum, size_t bucket_count) | 71 TimeDelta maximum, size_t bucket_count) |
| 75 : histogram_name_(name), | 72 : histogram_name_(name), |
| 76 declared_min_(static_cast<int> (minimum.InMilliseconds())), | 73 declared_min_(static_cast<int> (minimum.InMilliseconds())), |
| 77 declared_max_(static_cast<int> (maximum.InMilliseconds())), | 74 declared_max_(static_cast<int> (maximum.InMilliseconds())), |
| 78 bucket_count_(bucket_count), | 75 bucket_count_(bucket_count), |
| 79 flags_(0), | 76 flags_(kNoFlags), |
| 80 ranges_(bucket_count + 1, 0), | 77 ranges_(bucket_count + 1, 0), |
| 81 sample_() { | 78 sample_() { |
| 82 Initialize(); | 79 Initialize(); |
| 83 } | 80 } |
| 84 | 81 |
| 85 Histogram::~Histogram() { | 82 Histogram::~Histogram() { |
| 86 DCHECK(!(kPlannedLeakFlag & flags_)); | |
| 87 if (StatisticsRecorder::dump_on_exit()) { | 83 if (StatisticsRecorder::dump_on_exit()) { |
| 88 std::string output; | 84 std::string output; |
| 89 WriteAscii(true, "\n", &output); | 85 WriteAscii(true, "\n", &output); |
| 90 LOG(INFO) << output; | 86 LOG(INFO) << output; |
| 91 } | 87 } |
| 92 | 88 |
| 93 // Just to make sure most derived class did this properly... | 89 // Just to make sure most derived class did this properly... |
| 94 DCHECK(ValidateBucketRanges()); | 90 DCHECK(ValidateBucketRanges()); |
| 95 } | 91 } |
| 96 | 92 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 177 WriteAsciiBucketContext(past, current, remaining, i, output); | 173 WriteAsciiBucketContext(past, current, remaining, i, output); |
| 178 output->append(newline); | 174 output->append(newline); |
| 179 past += current; | 175 past += current; |
| 180 } | 176 } |
| 181 DCHECK(past == sample_count); | 177 DCHECK(past == sample_count); |
| 182 } | 178 } |
| 183 | 179 |
| 184 bool Histogram::ValidateBucketRanges() const { | 180 bool Histogram::ValidateBucketRanges() const { |
| 185 // Standard assertions that all bucket ranges should satisfy. | 181 // Standard assertions that all bucket ranges should satisfy. |
| 186 DCHECK(ranges_.size() == bucket_count_ + 1); | 182 DCHECK(ranges_.size() == bucket_count_ + 1); |
| 187 DCHECK(0 == ranges_[0]); | 183 DCHECK_EQ(0, ranges_[0]); |
| 188 DCHECK(declared_min() == ranges_[1]); | 184 DCHECK(declared_min() == ranges_[1]); |
| 189 DCHECK(declared_max() == ranges_[bucket_count_ - 1]); | 185 DCHECK(declared_max() == ranges_[bucket_count_ - 1]); |
| 190 DCHECK(kSampleType_MAX == ranges_[bucket_count_]); | 186 DCHECK(kSampleType_MAX == ranges_[bucket_count_]); |
| 191 return true; | 187 return true; |
| 192 } | 188 } |
| 193 | 189 |
| 194 void Histogram::Initialize() { | 190 void Histogram::Initialize() { |
| 195 sample_.Resize(*this); | 191 sample_.Resize(*this); |
| 196 if (declared_min_ <= 0) | 192 if (declared_min_ <= 0) |
| 197 declared_min_ = 1; | 193 declared_min_ = 1; |
| 198 if (declared_max_ >= kSampleType_MAX) | 194 if (declared_max_ >= kSampleType_MAX) |
| 199 declared_max_ = kSampleType_MAX - 1; | 195 declared_max_ = kSampleType_MAX - 1; |
| 200 DCHECK(declared_min_ > 0); // We provide underflow bucket. | 196 DCHECK_GT(declared_min_, 0); // We provide underflow bucket. |
| 201 DCHECK(declared_min_ <= declared_max_); | 197 DCHECK(declared_min_ <= declared_max_); |
| 202 DCHECK(1 < bucket_count_); | 198 DCHECK_LT(1u, bucket_count_); |
| 203 size_t maximal_bucket_count = declared_max_ - declared_min_ + 2; | 199 size_t maximal_bucket_count = declared_max_ - declared_min_ + 2; |
| 204 DCHECK(bucket_count_ <= maximal_bucket_count); | 200 DCHECK(bucket_count_ <= maximal_bucket_count); |
| 205 DCHECK(0 == ranges_[0]); | 201 DCHECK_EQ(0, ranges_[0]); |
| 206 ranges_[bucket_count_] = kSampleType_MAX; | 202 ranges_[bucket_count_] = kSampleType_MAX; |
| 207 InitializeBucketRange(); | 203 InitializeBucketRange(); |
| 208 DCHECK(ValidateBucketRanges()); | 204 DCHECK(ValidateBucketRanges()); |
| 209 StatisticsRecorder::Register(this); | 205 StatisticsRecorder::Register(this); |
| 210 } | 206 } |
| 211 | 207 |
| 212 // Calculate what range of values are held in each bucket. | 208 // Calculate what range of values are held in each bucket. |
| 213 // We have to be careful that we don't pick a ratio between starting points in | 209 // We have to be careful that we don't pick a ratio between starting points in |
| 214 // consecutive buckets that is sooo small, that the integer bounds are the same | 210 // consecutive buckets that is sooo small, that the integer bounds are the same |
| 215 // (effectively making one bucket get no values). We need to avoid: | 211 // (effectively making one bucket get no values). We need to avoid: |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 } | 319 } |
| 324 | 320 |
| 325 void Histogram::WriteAsciiHeader(const SampleSet& snapshot, | 321 void Histogram::WriteAsciiHeader(const SampleSet& snapshot, |
| 326 Count sample_count, | 322 Count sample_count, |
| 327 std::string* output) const { | 323 std::string* output) const { |
| 328 StringAppendF(output, | 324 StringAppendF(output, |
| 329 "Histogram: %s recorded %d samples", | 325 "Histogram: %s recorded %d samples", |
| 330 histogram_name().c_str(), | 326 histogram_name().c_str(), |
| 331 sample_count); | 327 sample_count); |
| 332 if (0 == sample_count) { | 328 if (0 == sample_count) { |
| 333 DCHECK(0 == snapshot.sum()); | 329 DCHECK_EQ(0, snapshot.sum()); |
| 334 } else { | 330 } else { |
| 335 double average = static_cast<float>(snapshot.sum()) / sample_count; | 331 double average = static_cast<float>(snapshot.sum()) / sample_count; |
| 336 double variance = static_cast<float>(snapshot.square_sum())/sample_count | 332 double variance = static_cast<float>(snapshot.square_sum())/sample_count |
| 337 - average * average; | 333 - average * average; |
| 338 double standard_deviation = sqrt(variance); | 334 double standard_deviation = sqrt(variance); |
| 339 | 335 |
| 340 StringAppendF(output, | 336 StringAppendF(output, |
| 341 ", average = %.1f, standard deviation = %.1f", | 337 ", average = %.1f, standard deviation = %.1f", |
| 342 average, standard_deviation); | 338 average, standard_deviation); |
| 343 } | 339 } |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 return false; | 405 return false; |
| 410 } | 406 } |
| 411 | 407 |
| 412 Pickle pickle(histogram_info.data(), | 408 Pickle pickle(histogram_info.data(), |
| 413 static_cast<int>(histogram_info.size())); | 409 static_cast<int>(histogram_info.size())); |
| 414 void* iter = NULL; | 410 void* iter = NULL; |
| 415 size_t bucket_count; | 411 size_t bucket_count; |
| 416 int declared_min; | 412 int declared_min; |
| 417 int declared_max; | 413 int declared_max; |
| 418 int histogram_type; | 414 int histogram_type; |
| 419 int flags; | 415 int pickle_flags; |
| 420 std::string histogram_name; | 416 std::string histogram_name; |
| 421 SampleSet sample; | 417 SampleSet sample; |
| 422 | 418 |
| 423 if (!pickle.ReadString(&iter, &histogram_name) || | 419 if (!pickle.ReadString(&iter, &histogram_name) || |
| 424 !pickle.ReadInt(&iter, &declared_min) || | 420 !pickle.ReadInt(&iter, &declared_min) || |
| 425 !pickle.ReadInt(&iter, &declared_max) || | 421 !pickle.ReadInt(&iter, &declared_max) || |
| 426 !pickle.ReadSize(&iter, &bucket_count) || | 422 !pickle.ReadSize(&iter, &bucket_count) || |
| 427 !pickle.ReadInt(&iter, &histogram_type) || | 423 !pickle.ReadInt(&iter, &histogram_type) || |
| 428 !pickle.ReadInt(&iter, &flags) || | 424 !pickle.ReadInt(&iter, &pickle_flags) || |
| 429 !sample.Histogram::SampleSet::Deserialize(&iter, pickle)) { | 425 !sample.Histogram::SampleSet::Deserialize(&iter, pickle)) { |
| 430 LOG(ERROR) << "Picke error decoding Histogram: " << histogram_name; | 426 LOG(ERROR) << "Picke error decoding Histogram: " << histogram_name; |
| 431 return false; | 427 return false; |
| 432 } | 428 } |
| 429 Flags flags = static_cast<Flags>(pickle_flags & ~kIPCSerializationSourceFlag); |
| 433 | 430 |
| 434 DCHECK(histogram_type != NOT_VALID_IN_RENDERER); | 431 DCHECK(histogram_type != NOT_VALID_IN_RENDERER); |
| 435 | 432 |
| 436 scoped_refptr<Histogram> render_histogram(NULL); | 433 scoped_refptr<Histogram> render_histogram(NULL); |
| 437 | 434 |
| 438 if (histogram_type == HISTOGRAM) { | 435 if (histogram_type == HISTOGRAM) { |
| 439 render_histogram = Histogram::HistogramFactoryGet( | 436 render_histogram = Histogram::FactoryGet( |
| 440 histogram_name, declared_min, declared_max, bucket_count); | 437 histogram_name, declared_min, declared_max, bucket_count, flags); |
| 441 } else if (histogram_type == LINEAR_HISTOGRAM) { | 438 } else if (histogram_type == LINEAR_HISTOGRAM) { |
| 442 render_histogram = LinearHistogram::LinearHistogramFactoryGet( | 439 render_histogram = LinearHistogram::FactoryGet( |
| 443 histogram_name, declared_min, declared_max, bucket_count); | 440 histogram_name, declared_min, declared_max, bucket_count, flags); |
| 444 } else if (histogram_type == BOOLEAN_HISTOGRAM) { | 441 } else if (histogram_type == BOOLEAN_HISTOGRAM) { |
| 445 render_histogram = BooleanHistogram::BooleanHistogramFactoryGet( | 442 render_histogram = BooleanHistogram::FactoryGet(histogram_name, flags); |
| 446 histogram_name); | |
| 447 } else if (histogram_type == THREAD_SAFE_HISTOGRAM) { | |
| 448 render_histogram = | |
| 449 ThreadSafeHistogram::ThreadSafeHistogramFactoryGet( | |
| 450 histogram_name, declared_min, declared_max, bucket_count); | |
| 451 } else { | 443 } else { |
| 452 LOG(ERROR) << "Error Deserializing Histogram Unknown histogram_type: " << | 444 LOG(ERROR) << "Error Deserializing Histogram Unknown histogram_type: " << |
| 453 histogram_type; | 445 histogram_type; |
| 454 return false; | 446 return false; |
| 455 } | 447 } |
| 456 | 448 |
| 457 DCHECK(declared_min == render_histogram->declared_min()); | 449 DCHECK(declared_min == render_histogram->declared_min()); |
| 458 DCHECK(declared_max == render_histogram->declared_max()); | 450 DCHECK(declared_max == render_histogram->declared_max()); |
| 459 DCHECK(bucket_count == render_histogram->bucket_count()); | 451 DCHECK(bucket_count == render_histogram->bucket_count()); |
| 460 DCHECK(histogram_type == render_histogram->histogram_type()); | 452 DCHECK(histogram_type == render_histogram->histogram_type()); |
| 461 | 453 |
| 462 if (render_histogram->flags() & kIPCSerializationSourceFlag) { | 454 if (render_histogram->flags() & kIPCSerializationSourceFlag) { |
| 463 DLOG(INFO) << "Single process mode, histogram observed and not copied: " << | 455 DLOG(INFO) << "Single process mode, histogram observed and not copied: " << |
| 464 histogram_name; | 456 histogram_name; |
| 465 } else { | 457 } else { |
| 458 DCHECK(flags == (flags & render_histogram->flags())); |
| 466 render_histogram->AddSampleSet(sample); | 459 render_histogram->AddSampleSet(sample); |
| 467 render_histogram->SetFlags(flags & ~kIPCSerializationSourceFlag | |
| 468 & ~kPlannedLeakFlag); | |
| 469 } | 460 } |
| 470 | 461 |
| 471 return true; | 462 return true; |
| 472 } | 463 } |
| 473 | 464 |
| 474 //------------------------------------------------------------------------------ | 465 //------------------------------------------------------------------------------ |
| 475 // Methods for the Histogram::SampleSet class | 466 // Methods for the Histogram::SampleSet class |
| 476 //------------------------------------------------------------------------------ | 467 //------------------------------------------------------------------------------ |
| 477 | 468 |
| 478 Histogram::SampleSet::SampleSet() | 469 Histogram::SampleSet::SampleSet() |
| (...skipping 10 matching lines...) Expand all Loading... |
| 489 DCHECK(counts_.size() == histogram.bucket_count()); | 480 DCHECK(counts_.size() == histogram.bucket_count()); |
| 490 } | 481 } |
| 491 | 482 |
| 492 | 483 |
| 493 void Histogram::SampleSet::Accumulate(Sample value, Count count, | 484 void Histogram::SampleSet::Accumulate(Sample value, Count count, |
| 494 size_t index) { | 485 size_t index) { |
| 495 DCHECK(count == 1 || count == -1); | 486 DCHECK(count == 1 || count == -1); |
| 496 counts_[index] += count; | 487 counts_[index] += count; |
| 497 sum_ += count * value; | 488 sum_ += count * value; |
| 498 square_sum_ += (count * value) * static_cast<int64>(value); | 489 square_sum_ += (count * value) * static_cast<int64>(value); |
| 499 DCHECK(counts_[index] >= 0); | 490 DCHECK_GE(counts_[index], 0); |
| 500 DCHECK(sum_ >= 0); | 491 DCHECK_GE(sum_, 0); |
| 501 DCHECK(square_sum_ >= 0); | 492 DCHECK_GE(square_sum_, 0); |
| 502 } | 493 } |
| 503 | 494 |
| 504 Count Histogram::SampleSet::TotalCount() const { | 495 Count Histogram::SampleSet::TotalCount() const { |
| 505 Count total = 0; | 496 Count total = 0; |
| 506 for (Counts::const_iterator it = counts_.begin(); | 497 for (Counts::const_iterator it = counts_.begin(); |
| 507 it != counts_.end(); | 498 it != counts_.end(); |
| 508 ++it) { | 499 ++it) { |
| 509 total += *it; | 500 total += *it; |
| 510 } | 501 } |
| 511 return total; | 502 return total; |
| 512 } | 503 } |
| 513 | 504 |
| 514 void Histogram::SampleSet::Add(const SampleSet& other) { | 505 void Histogram::SampleSet::Add(const SampleSet& other) { |
| 515 DCHECK(counts_.size() == other.counts_.size()); | 506 DCHECK(counts_.size() == other.counts_.size()); |
| 516 sum_ += other.sum_; | 507 sum_ += other.sum_; |
| 517 square_sum_ += other.square_sum_; | 508 square_sum_ += other.square_sum_; |
| 518 for (size_t index = 0; index < counts_.size(); ++index) | 509 for (size_t index = 0; index < counts_.size(); ++index) |
| 519 counts_[index] += other.counts_[index]; | 510 counts_[index] += other.counts_[index]; |
| 520 } | 511 } |
| 521 | 512 |
| 522 void Histogram::SampleSet::Subtract(const SampleSet& other) { | 513 void Histogram::SampleSet::Subtract(const SampleSet& other) { |
| 523 DCHECK(counts_.size() == other.counts_.size()); | 514 DCHECK(counts_.size() == other.counts_.size()); |
| 524 // Note: Race conditions in snapshotting a sum or square_sum may lead to | 515 // Note: Race conditions in snapshotting a sum or square_sum may lead to |
| 525 // (temporary) negative values when snapshots are later combined (and deltas | 516 // (temporary) negative values when snapshots are later combined (and deltas |
| 526 // calculated). As a result, we don't currently CHCEK() for positive values. | 517 // calculated). As a result, we don't currently CHCEK() for positive values. |
| 527 sum_ -= other.sum_; | 518 sum_ -= other.sum_; |
| 528 square_sum_ -= other.square_sum_; | 519 square_sum_ -= other.square_sum_; |
| 529 for (size_t index = 0; index < counts_.size(); ++index) { | 520 for (size_t index = 0; index < counts_.size(); ++index) { |
| 530 counts_[index] -= other.counts_[index]; | 521 counts_[index] -= other.counts_[index]; |
| 531 DCHECK(counts_[index] >= 0); | 522 DCHECK_GE(counts_[index], 0); |
| 532 } | 523 } |
| 533 } | 524 } |
| 534 | 525 |
| 535 bool Histogram::SampleSet::Serialize(Pickle* pickle) const { | 526 bool Histogram::SampleSet::Serialize(Pickle* pickle) const { |
| 536 pickle->WriteInt64(sum_); | 527 pickle->WriteInt64(sum_); |
| 537 pickle->WriteInt64(square_sum_); | 528 pickle->WriteInt64(square_sum_); |
| 538 pickle->WriteSize(counts_.size()); | 529 pickle->WriteSize(counts_.size()); |
| 539 | 530 |
| 540 for (size_t index = 0; index < counts_.size(); ++index) { | 531 for (size_t index = 0; index < counts_.size(); ++index) { |
| 541 pickle->WriteInt(counts_[index]); | 532 pickle->WriteInt(counts_[index]); |
| 542 } | 533 } |
| 543 | 534 |
| 544 return true; | 535 return true; |
| 545 } | 536 } |
| 546 | 537 |
| 547 bool Histogram::SampleSet::Deserialize(void** iter, const Pickle& pickle) { | 538 bool Histogram::SampleSet::Deserialize(void** iter, const Pickle& pickle) { |
| 548 DCHECK(counts_.size() == 0); | 539 DCHECK_EQ(counts_.size(), 0u); |
| 549 DCHECK(sum_ == 0); | 540 DCHECK_EQ(sum_, 0); |
| 550 DCHECK(square_sum_ == 0); | 541 DCHECK_EQ(square_sum_, 0); |
| 551 | 542 |
| 552 size_t counts_size; | 543 size_t counts_size; |
| 553 | 544 |
| 554 if (!pickle.ReadInt64(iter, &sum_) || | 545 if (!pickle.ReadInt64(iter, &sum_) || |
| 555 !pickle.ReadInt64(iter, &square_sum_) || | 546 !pickle.ReadInt64(iter, &square_sum_) || |
| 556 !pickle.ReadSize(iter, &counts_size)) { | 547 !pickle.ReadSize(iter, &counts_size)) { |
| 557 return false; | 548 return false; |
| 558 } | 549 } |
| 559 | 550 |
| 560 if (counts_size <= 0) | 551 if (counts_size <= 0) |
| 561 return false; | 552 return false; |
| 562 | 553 |
| 563 counts_.resize(counts_size, 0); | 554 counts_.resize(counts_size, 0); |
| 564 for (size_t index = 0; index < counts_size; ++index) { | 555 for (size_t index = 0; index < counts_size; ++index) { |
| 565 if (!pickle.ReadInt(iter, &counts_[index])) { | 556 if (!pickle.ReadInt(iter, &counts_[index])) { |
| 566 return false; | 557 return false; |
| 567 } | 558 } |
| 568 } | 559 } |
| 569 | 560 |
| 570 return true; | 561 return true; |
| 571 } | 562 } |
| 572 | 563 |
| 573 //------------------------------------------------------------------------------ | 564 //------------------------------------------------------------------------------ |
| 574 // LinearHistogram: This histogram uses a traditional set of evenly spaced | 565 // LinearHistogram: This histogram uses a traditional set of evenly spaced |
| 575 // buckets. | 566 // buckets. |
| 576 //------------------------------------------------------------------------------ | 567 //------------------------------------------------------------------------------ |
| 577 | 568 |
| 578 scoped_refptr<Histogram> LinearHistogram::LinearHistogramFactoryGet( | 569 scoped_refptr<Histogram> LinearHistogram::FactoryGet( |
| 579 const std::string& name, Sample minimum, Sample maximum, | 570 const std::string& name, Sample minimum, Sample maximum, |
| 580 size_t bucket_count) { | 571 size_t bucket_count, Flags flags) { |
| 581 scoped_refptr<Histogram> histogram(NULL); | 572 scoped_refptr<Histogram> histogram(NULL); |
| 582 | 573 |
| 583 if (minimum <= 0) | 574 if (minimum <= 0) |
| 584 minimum = 1; | 575 minimum = 1; |
| 585 if (maximum >= kSampleType_MAX) | 576 if (maximum >= kSampleType_MAX) |
| 586 maximum = kSampleType_MAX - 1; | 577 maximum = kSampleType_MAX - 1; |
| 587 | 578 |
| 588 if (StatisticsRecorder::FindHistogram(name, &histogram)) { | 579 if (StatisticsRecorder::FindHistogram(name, &histogram)) { |
| 589 DCHECK(histogram.get() != NULL); | 580 DCHECK(histogram.get() != NULL); |
| 590 } else { | 581 } else { |
| 591 histogram = new LinearHistogram(name, minimum, maximum, bucket_count); | 582 histogram = new LinearHistogram(name, minimum, maximum, bucket_count); |
| 592 scoped_refptr<Histogram> registered_histogram(NULL); | 583 scoped_refptr<Histogram> registered_histogram(NULL); |
| 593 StatisticsRecorder::FindHistogram(name, ®istered_histogram); | 584 StatisticsRecorder::FindHistogram(name, ®istered_histogram); |
| 594 if (registered_histogram.get() != NULL && | 585 if (registered_histogram.get() != NULL && |
| 595 registered_histogram.get() != histogram.get()) | 586 registered_histogram.get() != histogram.get()) |
| 596 histogram = registered_histogram; | 587 histogram = registered_histogram; |
| 597 } | 588 } |
| 598 | 589 |
| 599 DCHECK(LINEAR_HISTOGRAM == histogram->histogram_type()); | 590 DCHECK(LINEAR_HISTOGRAM == histogram->histogram_type()); |
| 600 DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count)); | 591 DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count)); |
| 601 | 592 histogram->SetFlags(flags); |
| 602 return histogram; | 593 return histogram; |
| 603 } | 594 } |
| 604 | 595 |
| 605 scoped_refptr<Histogram> LinearHistogram::LinearHistogramFactoryGet( | 596 scoped_refptr<Histogram> LinearHistogram::FactoryGet(const std::string& name, |
| 606 const std::string& name, base::TimeDelta minimum, base::TimeDelta maximum, | 597 base::TimeDelta minimum, base::TimeDelta maximum, size_t bucket_count, |
| 607 size_t bucket_count) { | 598 Flags flags) { |
| 608 return LinearHistogramFactoryGet(name, minimum.InMilliseconds(), | 599 return FactoryGet(name, minimum.InMilliseconds(), maximum.InMilliseconds(), |
| 609 maximum.InMilliseconds(), bucket_count); | 600 bucket_count, flags); |
| 610 } | 601 } |
| 611 | 602 |
| 612 LinearHistogram::LinearHistogram(const std::string& name, Sample minimum, | 603 LinearHistogram::LinearHistogram(const std::string& name, Sample minimum, |
| 613 Sample maximum, size_t bucket_count) | 604 Sample maximum, size_t bucket_count) |
| 614 : Histogram(name, minimum >= 1 ? minimum : 1, maximum, bucket_count) { | 605 : Histogram(name, minimum >= 1 ? minimum : 1, maximum, bucket_count) { |
| 615 InitializeBucketRange(); | 606 InitializeBucketRange(); |
| 616 DCHECK(ValidateBucketRanges()); | 607 DCHECK(ValidateBucketRanges()); |
| 617 } | 608 } |
| 618 | 609 |
| 619 LinearHistogram::LinearHistogram(const std::string& name, | 610 LinearHistogram::LinearHistogram(const std::string& name, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 640 return Histogram::GetAsciiBucketRange(i); | 631 return Histogram::GetAsciiBucketRange(i); |
| 641 return it->second; | 632 return it->second; |
| 642 } | 633 } |
| 643 | 634 |
| 644 bool LinearHistogram::PrintEmptyBucket(size_t index) const { | 635 bool LinearHistogram::PrintEmptyBucket(size_t index) const { |
| 645 return bucket_description_.find(ranges(index)) == bucket_description_.end(); | 636 return bucket_description_.find(ranges(index)) == bucket_description_.end(); |
| 646 } | 637 } |
| 647 | 638 |
| 648 | 639 |
| 649 void LinearHistogram::InitializeBucketRange() { | 640 void LinearHistogram::InitializeBucketRange() { |
| 650 DCHECK(0 < declared_min()); // 0 is the underflow bucket here. | 641 DCHECK_LT(0, declared_min()); // 0 is the underflow bucket here. |
| 651 double min = declared_min(); | 642 double min = declared_min(); |
| 652 double max = declared_max(); | 643 double max = declared_max(); |
| 653 size_t i; | 644 size_t i; |
| 654 for (i = 1; i < bucket_count(); ++i) { | 645 for (i = 1; i < bucket_count(); ++i) { |
| 655 double linear_range = (min * (bucket_count() -1 - i) + max * (i - 1)) / | 646 double linear_range = (min * (bucket_count() -1 - i) + max * (i - 1)) / |
| 656 (bucket_count() - 2); | 647 (bucket_count() - 2); |
| 657 SetBucketRange(i, static_cast<int> (linear_range + 0.5)); | 648 SetBucketRange(i, static_cast<int> (linear_range + 0.5)); |
| 658 } | 649 } |
| 659 } | 650 } |
| 660 | 651 |
| 661 double LinearHistogram::GetBucketSize(Count current, size_t i) const { | 652 double LinearHistogram::GetBucketSize(Count current, size_t i) const { |
| 662 DCHECK(ranges(i + 1) > ranges(i)); | 653 DCHECK(ranges(i + 1) > ranges(i)); |
| 663 // Adjacent buckets with different widths would have "surprisingly" many (few) | 654 // Adjacent buckets with different widths would have "surprisingly" many (few) |
| 664 // samples in a histogram if we didn't normalize this way. | 655 // samples in a histogram if we didn't normalize this way. |
| 665 double denominator = ranges(i + 1) - ranges(i); | 656 double denominator = ranges(i + 1) - ranges(i); |
| 666 return current/denominator; | 657 return current/denominator; |
| 667 } | 658 } |
| 668 | 659 |
| 669 //------------------------------------------------------------------------------ | 660 //------------------------------------------------------------------------------ |
| 670 // This section provides implementation for BooleanHistogram. | 661 // This section provides implementation for BooleanHistogram. |
| 671 //------------------------------------------------------------------------------ | 662 //------------------------------------------------------------------------------ |
| 672 | 663 |
| 673 scoped_refptr<Histogram> BooleanHistogram::BooleanHistogramFactoryGet( | 664 scoped_refptr<Histogram> BooleanHistogram::FactoryGet(const std::string& name, |
| 674 const std::string& name) { | 665 Flags flags) { |
| 675 scoped_refptr<Histogram> histogram(NULL); | 666 scoped_refptr<Histogram> histogram(NULL); |
| 676 | 667 |
| 677 if (StatisticsRecorder::FindHistogram(name, &histogram)) { | 668 if (StatisticsRecorder::FindHistogram(name, &histogram)) { |
| 678 DCHECK(histogram.get() != NULL); | 669 DCHECK(histogram.get() != NULL); |
| 679 } else { | 670 } else { |
| 680 histogram = new BooleanHistogram(name); | 671 histogram = new BooleanHistogram(name); |
| 681 scoped_refptr<Histogram> registered_histogram(NULL); | 672 scoped_refptr<Histogram> registered_histogram(NULL); |
| 682 StatisticsRecorder::FindHistogram(name, ®istered_histogram); | 673 StatisticsRecorder::FindHistogram(name, ®istered_histogram); |
| 683 if (registered_histogram.get() != NULL && | 674 if (registered_histogram.get() != NULL && |
| 684 registered_histogram.get() != histogram.get()) | 675 registered_histogram.get() != histogram.get()) |
| 685 histogram = registered_histogram; | 676 histogram = registered_histogram; |
| 686 } | 677 } |
| 687 | 678 |
| 688 DCHECK(BOOLEAN_HISTOGRAM == histogram->histogram_type()); | 679 DCHECK(BOOLEAN_HISTOGRAM == histogram->histogram_type()); |
| 689 | 680 histogram->SetFlags(flags); |
| 690 return histogram; | 681 return histogram; |
| 691 } | 682 } |
| 692 | 683 |
| 693 //------------------------------------------------------------------------------ | |
| 694 // This section provides implementation for ThreadSafeHistogram. | |
| 695 //------------------------------------------------------------------------------ | |
| 696 | |
| 697 scoped_refptr<Histogram> ThreadSafeHistogram::ThreadSafeHistogramFactoryGet( | |
| 698 const std::string& name, Sample minimum, Sample maximum, | |
| 699 size_t bucket_count) { | |
| 700 scoped_refptr<Histogram> histogram(NULL); | |
| 701 | |
| 702 if (minimum <= 0) | |
| 703 minimum = 1; | |
| 704 if (maximum >= kSampleType_MAX) | |
| 705 maximum = kSampleType_MAX - 1; | |
| 706 | |
| 707 if (StatisticsRecorder::FindHistogram(name, &histogram)) { | |
| 708 DCHECK(histogram.get() != NULL); | |
| 709 } else { | |
| 710 histogram = new ThreadSafeHistogram(name, minimum, maximum, bucket_count); | |
| 711 scoped_refptr<Histogram> registered_histogram(NULL); | |
| 712 StatisticsRecorder::FindHistogram(name, ®istered_histogram); | |
| 713 if (registered_histogram.get() != NULL && | |
| 714 registered_histogram.get() != histogram.get()) | |
| 715 histogram = registered_histogram; | |
| 716 } | |
| 717 | |
| 718 DCHECK(THREAD_SAFE_HISTOGRAM == histogram->histogram_type()); | |
| 719 DCHECK(histogram->HasConstructorArguments(minimum, maximum, bucket_count)); | |
| 720 return histogram; | |
| 721 } | |
| 722 | |
| 723 ThreadSafeHistogram::ThreadSafeHistogram(const std::string& name, | |
| 724 Sample minimum, Sample maximum, size_t bucket_count) | |
| 725 : Histogram(name, minimum, maximum, bucket_count), | |
| 726 lock_() { | |
| 727 } | |
| 728 | |
| 729 void ThreadSafeHistogram::Remove(int value) { | |
| 730 if (value >= kSampleType_MAX) | |
| 731 value = kSampleType_MAX - 1; | |
| 732 size_t index = BucketIndex(value); | |
| 733 Accumulate(value, -1, index); | |
| 734 } | |
| 735 | |
| 736 void ThreadSafeHistogram::Accumulate(Sample value, Count count, size_t index) { | |
| 737 AutoLock lock(lock_); | |
| 738 Histogram::Accumulate(value, count, index); | |
| 739 } | |
| 740 | |
| 741 void ThreadSafeHistogram::SnapshotSample(SampleSet* sample) const { | |
| 742 AutoLock lock(lock_); | |
| 743 Histogram::SnapshotSample(sample); | |
| 744 }; | |
| 745 | |
| 746 | 684 |
| 747 //------------------------------------------------------------------------------ | 685 //------------------------------------------------------------------------------ |
| 748 // The next section handles global (central) support for all histograms, as well | 686 // The next section handles global (central) support for all histograms, as well |
| 749 // as startup/teardown of this service. | 687 // as startup/teardown of this service. |
| 750 //------------------------------------------------------------------------------ | 688 //------------------------------------------------------------------------------ |
| 751 | 689 |
| 752 // This singleton instance should be started during the single threaded portion | 690 // This singleton instance should be started during the single threaded portion |
| 753 // of main(), and hence it is not thread safe. It initializes globals to | 691 // of main(), and hence it is not thread safe. It initializes globals to |
| 754 // provide support for all future calls. | 692 // provide support for all future calls. |
| 755 StatisticsRecorder::StatisticsRecorder() { | 693 StatisticsRecorder::StatisticsRecorder() { |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 855 | 793 |
| 856 // static | 794 // static |
| 857 void StatisticsRecorder::GetHistogramsForRenderer(Histograms* output) { | 795 void StatisticsRecorder::GetHistogramsForRenderer(Histograms* output) { |
| 858 if (!histograms_) | 796 if (!histograms_) |
| 859 return; | 797 return; |
| 860 AutoLock auto_lock(*lock_); | 798 AutoLock auto_lock(*lock_); |
| 861 for (HistogramMap::iterator it = histograms_->begin(); | 799 for (HistogramMap::iterator it = histograms_->begin(); |
| 862 histograms_->end() != it; | 800 histograms_->end() != it; |
| 863 ++it) { | 801 ++it) { |
| 864 scoped_refptr<Histogram> histogram = it->second; | 802 scoped_refptr<Histogram> histogram = it->second; |
| 865 if (!(histogram->flags() & kIPCSerializationSourceFlag)) | 803 if (!(histogram->flags() & Histogram::kIPCSerializationSourceFlag)) |
| 866 histogram->SetFlags(kIPCSerializationSourceFlag); | 804 histogram->SetFlags(Histogram::kIPCSerializationSourceFlag); |
| 867 output->push_back(histogram); | 805 output->push_back(histogram); |
| 868 } | 806 } |
| 869 } | 807 } |
| 870 | 808 |
| 871 bool StatisticsRecorder::FindHistogram(const std::string& name, | 809 bool StatisticsRecorder::FindHistogram(const std::string& name, |
| 872 scoped_refptr<Histogram>* histogram) { | 810 scoped_refptr<Histogram>* histogram) { |
| 873 if (!histograms_) | 811 if (!histograms_) |
| 874 return false; | 812 return false; |
| 875 AutoLock auto_lock(*lock_); | 813 AutoLock auto_lock(*lock_); |
| 876 HistogramMap::iterator it = histograms_->find(name); | 814 HistogramMap::iterator it = histograms_->find(name); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 891 snapshot->push_back(it->second); | 829 snapshot->push_back(it->second); |
| 892 } | 830 } |
| 893 } | 831 } |
| 894 | 832 |
| 895 // static | 833 // static |
| 896 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; | 834 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; |
| 897 // static | 835 // static |
| 898 Lock* StatisticsRecorder::lock_ = NULL; | 836 Lock* StatisticsRecorder::lock_ = NULL; |
| 899 // static | 837 // static |
| 900 bool StatisticsRecorder::dump_on_exit_ = false; | 838 bool StatisticsRecorder::dump_on_exit_ = false; |
| OLD | NEW |