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 |