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

Side by Side Diff: base/histogram.cc

Issue 27034: Initial support for Renderer Side Histograms... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/histogram.h ('k') | chrome/browser/browser_about_handler.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 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"
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 bucket_count_(bucket_count), 46 bucket_count_(bucket_count),
47 flags_(0), 47 flags_(0),
48 ranges_(bucket_count + 1, 0), 48 ranges_(bucket_count + 1, 0),
49 sample_(), 49 sample_(),
50 registered_(false) { 50 registered_(false) {
51 Initialize(); 51 Initialize();
52 } 52 }
53 53
54 Histogram::~Histogram() { 54 Histogram::~Histogram() {
55 if (registered_) 55 if (registered_)
56 StatisticsRecorder::UnRegister(*this); 56 StatisticsRecorder::UnRegister(this);
57 // Just to make sure most derived class did this properly... 57 // Just to make sure most derived class did this properly...
58 DCHECK(ValidateBucketRanges()); 58 DCHECK(ValidateBucketRanges());
59 } 59 }
60 60
61
62 // Hooks to override stats counter methods. This ensures that we gather all 61 // Hooks to override stats counter methods. This ensures that we gather all
63 // input the stats counter sees. 62 // input the stats counter sees.
64 void Histogram::Add(int value) { 63 void Histogram::Add(int value) {
65 if (!registered_) 64 if (!registered_)
66 registered_ = StatisticsRecorder::Register(*this); 65 registered_ = StatisticsRecorder::Register(this);
67 if (value >= kSampleType_MAX) 66 if (value >= kSampleType_MAX)
68 value = kSampleType_MAX - 1; 67 value = kSampleType_MAX - 1;
69 StatsRate::Add(value); 68 StatsRate::Add(value);
70 if (value < 0) 69 if (value < 0)
71 value = 0; 70 value = 0;
72 size_t index = BucketIndex(value); 71 size_t index = BucketIndex(value);
73 DCHECK(value >= ranges(index)); 72 DCHECK(value >= ranges(index));
74 DCHECK(value < ranges(index + 1)); 73 DCHECK(value < ranges(index + 1));
75 Accumulate(value, 1, index); 74 Accumulate(value, 1, index);
76 } 75 }
77 76
77 void Histogram::AddSampleSet(const SampleSet& sample) {
78 sample_.Add(sample);
79 }
80
78 // The following methods provide a graphical histogram display. 81 // The following methods provide a graphical histogram display.
79 void Histogram::WriteHTMLGraph(std::string* output) const { 82 void Histogram::WriteHTMLGraph(std::string* output) const {
80 // TBD(jar) Write a nice HTML bar chart, with divs an mouse-overs etc. 83 // TBD(jar) Write a nice HTML bar chart, with divs an mouse-overs etc.
81 output->append("<PRE>"); 84 output->append("<PRE>");
82 WriteAscii(true, "<br>", output); 85 WriteAscii(true, "<br>", output);
83 output->append("</PRE>"); 86 output->append("</PRE>");
84 } 87 }
85 88
86 void Histogram::WriteAscii(bool graph_it, const std::string& newline, 89 void Histogram::WriteAscii(bool graph_it, const std::string& newline,
87 std::string* output) const { 90 std::string* output) const {
(...skipping 10 matching lines...) Expand all
98 double max_size = 0; 101 double max_size = 0;
99 if (graph_it) 102 if (graph_it)
100 max_size = GetPeakBucketSize(snapshot); 103 max_size = GetPeakBucketSize(snapshot);
101 104
102 // Calculate space needed to print bucket range numbers. Leave room to print 105 // Calculate space needed to print bucket range numbers. Leave room to print
103 // nearly the largest bucket range without sliding over the histogram. 106 // nearly the largest bucket range without sliding over the histogram.
104 size_t largest_non_empty_bucket = bucket_count() - 1; 107 size_t largest_non_empty_bucket = bucket_count() - 1;
105 while (0 == snapshot.counts(largest_non_empty_bucket)) { 108 while (0 == snapshot.counts(largest_non_empty_bucket)) {
106 if (0 == largest_non_empty_bucket) 109 if (0 == largest_non_empty_bucket)
107 break; // All buckets are empty. 110 break; // All buckets are empty.
108 largest_non_empty_bucket--; 111 --largest_non_empty_bucket;
109 } 112 }
110 113
111 // Calculate largest print width needed for any of our bucket range displays. 114 // Calculate largest print width needed for any of our bucket range displays.
112 size_t print_width = 1; 115 size_t print_width = 1;
113 for (size_t i = 0; i < bucket_count(); ++i) { 116 for (size_t i = 0; i < bucket_count(); ++i) {
114 if (snapshot.counts(i)) { 117 if (snapshot.counts(i)) {
115 size_t width = GetAsciiBucketRange(i).size() + 1; 118 size_t width = GetAsciiBucketRange(i).size() + 1;
116 if (width > print_width) 119 if (width > print_width)
117 print_width = width; 120 print_width = width;
118 } 121 }
119 } 122 }
120 123
121 int64 remaining = sample_count; 124 int64 remaining = sample_count;
122 int64 past = 0; 125 int64 past = 0;
123 // Output the actual histogram graph. 126 // Output the actual histogram graph.
124 for (size_t i = 0; i < bucket_count(); i++) { 127 for (size_t i = 0; i < bucket_count(); ++i) {
125 Count current = snapshot.counts(i); 128 Count current = snapshot.counts(i);
126 if (!current && !PrintEmptyBucket(i)) 129 if (!current && !PrintEmptyBucket(i))
127 continue; 130 continue;
128 remaining -= current; 131 remaining -= current;
129 StringAppendF(output, "%#*s ", print_width, GetAsciiBucketRange(i).c_str()); 132 StringAppendF(output, "%#*s ", print_width, GetAsciiBucketRange(i).c_str());
130 if (0 == current && i < bucket_count() - 1 && 0 == snapshot.counts(i + 1)) { 133 if (0 == current && i < bucket_count() - 1 && 0 == snapshot.counts(i + 1)) {
131 while (i < bucket_count() - 1 && 0 == snapshot.counts(i + 1)) 134 while (i < bucket_count() - 1 && 0 == snapshot.counts(i + 1))
132 i++; 135 ++i;
133 output->append("... "); 136 output->append("... ");
134 output->append(newline); 137 output->append(newline);
135 continue; // No reason to plot emptiness. 138 continue; // No reason to plot emptiness.
136 } 139 }
137 double current_size = GetBucketSize(current, i); 140 double current_size = GetBucketSize(current, i);
138 if (graph_it) 141 if (graph_it)
139 WriteAsciiBucketGraph(current_size, max_size, output); 142 WriteAsciiBucketGraph(current_size, max_size, output);
140 WriteAsciiBucketContext(past, current, remaining, i, output); 143 WriteAsciiBucketContext(past, current, remaining, i, output);
141 output->append(newline); 144 output->append(newline);
142 past += current; 145 past += current;
(...skipping 19 matching lines...) Expand all
162 declared_max_ = kSampleType_MAX - 1; 165 declared_max_ = kSampleType_MAX - 1;
163 DCHECK(declared_min_ > 0); // We provide underflow bucket. 166 DCHECK(declared_min_ > 0); // We provide underflow bucket.
164 DCHECK(declared_min_ <= declared_max_); 167 DCHECK(declared_min_ <= declared_max_);
165 DCHECK(1 < bucket_count_); 168 DCHECK(1 < bucket_count_);
166 size_t maximal_bucket_count = declared_max_ - declared_min_ + 2; 169 size_t maximal_bucket_count = declared_max_ - declared_min_ + 2;
167 DCHECK(bucket_count_ <= maximal_bucket_count); 170 DCHECK(bucket_count_ <= maximal_bucket_count);
168 DCHECK(0 == ranges_[0]); 171 DCHECK(0 == ranges_[0]);
169 ranges_[bucket_count_] = kSampleType_MAX; 172 ranges_[bucket_count_] = kSampleType_MAX;
170 InitializeBucketRange(); 173 InitializeBucketRange();
171 DCHECK(ValidateBucketRanges()); 174 DCHECK(ValidateBucketRanges());
172 registered_ = StatisticsRecorder::Register(*this); 175 registered_ = StatisticsRecorder::Register(this);
173 } 176 }
174 177
175 // Calculate what range of values are held in each bucket. 178 // Calculate what range of values are held in each bucket.
176 // We have to be careful that we don't pick a ratio between starting points in 179 // We have to be careful that we don't pick a ratio between starting points in
177 // consecutive buckets that is sooo small, that the integer bounds are the same 180 // consecutive buckets that is sooo small, that the integer bounds are the same
178 // (effectively making one bucket get no values). We need to avoid: 181 // (effectively making one bucket get no values). We need to avoid:
179 // (ranges_[i] == ranges_[i + 1] 182 // (ranges_[i] == ranges_[i + 1]
180 // To avoid that, we just do a fine-grained bucket width as far as we need to 183 // To avoid that, we just do a fine-grained bucket width as far as we need to
181 // until we get a ratio that moves us along at least 2 units at a time. From 184 // until we get a ratio that moves us along at least 2 units at a time. From
182 // that bucket onward we do use the exponential growth of buckets. 185 // that bucket onward we do use the exponential growth of buckets.
183 void Histogram::InitializeBucketRange() { 186 void Histogram::InitializeBucketRange() {
184 double log_max = log(static_cast<double>(declared_max())); 187 double log_max = log(static_cast<double>(declared_max()));
185 double log_ratio; 188 double log_ratio;
186 double log_next; 189 double log_next;
187 size_t bucket_index = 1; 190 size_t bucket_index = 1;
188 Sample current = declared_min(); 191 Sample current = declared_min();
189 SetBucketRange(bucket_index, current); 192 SetBucketRange(bucket_index, current);
190 while (bucket_count() > ++bucket_index) { 193 while (bucket_count() > ++bucket_index) {
191 double log_current; 194 double log_current;
192 log_current = log(static_cast<double>(current)); 195 log_current = log(static_cast<double>(current));
193 // Calculate the count'th root of the range. 196 // Calculate the count'th root of the range.
194 log_ratio = (log_max - log_current) / (bucket_count() - bucket_index); 197 log_ratio = (log_max - log_current) / (bucket_count() - bucket_index);
195 // See where the next bucket would start. 198 // See where the next bucket would start.
196 log_next = log_current + log_ratio; 199 log_next = log_current + log_ratio;
197 int next; 200 int next;
198 next = static_cast<int>(floor(exp(log_next) + 0.5)); 201 next = static_cast<int>(floor(exp(log_next) + 0.5));
199 if (next > current) 202 if (next > current)
200 current = next; 203 current = next;
201 else 204 else
202 current++; // Just do a narrow bucket, and keep trying. 205 ++current; // Just do a narrow bucket, and keep trying.
203 SetBucketRange(bucket_index, current); 206 SetBucketRange(bucket_index, current);
204 } 207 }
205 208
206 DCHECK(bucket_count() == bucket_index); 209 DCHECK(bucket_count() == bucket_index);
207 } 210 }
208 211
209 size_t Histogram::BucketIndex(Sample value) const { 212 size_t Histogram::BucketIndex(Sample value) const {
210 // Use simple binary search. This is very general, but there are better 213 // Use simple binary search. This is very general, but there are better
211 // approaches if we knew that the buckets were linearly distributed. 214 // approaches if we knew that the buckets were linearly distributed.
212 DCHECK(ranges(0) <= value); 215 DCHECK(ranges(0) <= value);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 void Histogram::SetBucketRange(size_t i, Sample value) { 273 void Histogram::SetBucketRange(size_t i, Sample value) {
271 DCHECK(bucket_count_ > i); 274 DCHECK(bucket_count_ > i);
272 ranges_[i] = value; 275 ranges_[i] = value;
273 } 276 }
274 277
275 //------------------------------------------------------------------------------ 278 //------------------------------------------------------------------------------
276 // Private methods 279 // Private methods
277 280
278 double Histogram::GetPeakBucketSize(const SampleSet& snapshot) const { 281 double Histogram::GetPeakBucketSize(const SampleSet& snapshot) const {
279 double max = 0; 282 double max = 0;
280 for (size_t i = 0; i < bucket_count() ; i++) { 283 for (size_t i = 0; i < bucket_count() ; ++i) {
281 double current_size = GetBucketSize(snapshot.counts(i), i); 284 double current_size = GetBucketSize(snapshot.counts(i), i);
282 if (current_size > max) 285 if (current_size > max)
283 max = current_size; 286 max = current_size;
284 } 287 }
285 return max; 288 return max;
286 } 289 }
287 290
288 void Histogram::WriteAsciiHeader(const SampleSet& snapshot, 291 void Histogram::WriteAsciiHeader(const SampleSet& snapshot,
289 Count sample_count, 292 Count sample_count,
290 std::string* output) const { 293 std::string* output) const {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 + 0.5); 345 + 0.5);
343 int x_remainder = k_line_length - x_count; 346 int x_remainder = k_line_length - x_count;
344 347
345 while (0 < x_count--) 348 while (0 < x_count--)
346 output->append("-"); 349 output->append("-");
347 output->append("O"); 350 output->append("O");
348 while (0 < x_remainder--) 351 while (0 < x_remainder--)
349 output->append(" "); 352 output->append(" ");
350 } 353 }
351 354
355 // static
356 std::string Histogram::SerializeHistogramInfo(const Histogram& histogram,
357 const SampleSet& snapshot) {
358 Pickle pickle;
359
360 pickle.WriteString(histogram.histogram_name());
361 pickle.WriteInt(histogram.declared_min());
362 pickle.WriteInt(histogram.declared_max());
363 pickle.WriteSize(histogram.bucket_count());
364 pickle.WriteInt(histogram.histogram_type());
365 pickle.WriteInt(histogram.flags());
366
367 snapshot.Serialize(&pickle);
368 return std::string(static_cast<const char*>(pickle.data()), pickle.size());
369 }
370
371 // static
372 void Histogram::DeserializeHistogramList(
373 const std::vector<std::string>& histograms) {
374 for (std::vector<std::string>::const_iterator it = histograms.begin();
375 it < histograms.end();
376 ++it) {
377 DeserializeHistogramInfo(*it);
378 }
379 }
380
381 // static
382 bool Histogram::DeserializeHistogramInfo(const std::string& histogram_info) {
383 if (histogram_info.empty()) {
384 return false;
385 }
386
387 Pickle pickle(histogram_info.data(),
388 static_cast<int>(histogram_info.size()));
389 void* iter = NULL;
390 size_t bucket_count;
391 int declared_min;
392 int declared_max;
393 int histogram_type;
394 int flags;
395 std::string histogram_name;
396 SampleSet sample;
397
398 if (!pickle.ReadString(&iter, &histogram_name) ||
399 !pickle.ReadInt(&iter, &declared_min) ||
400 !pickle.ReadInt(&iter, &declared_max) ||
401 !pickle.ReadSize(&iter, &bucket_count) ||
402 !pickle.ReadInt(&iter, &histogram_type) ||
403 !pickle.ReadInt(&iter, &flags) ||
404 !sample.Histogram::SampleSet::Deserialize(&iter, pickle)) {
405 LOG(ERROR) << "Picke error decoding Histogram: " << histogram_name;
406 return false;
407 }
408
409 Histogram* render_histogram =
410 StatisticsRecorder::GetHistogram(histogram_name);
411
412 if (render_histogram == NULL) {
413 if (histogram_type == EXPONENTIAL) {
414 render_histogram = new Histogram(histogram_name.c_str(),
415 declared_min,
416 declared_max,
417 bucket_count);
418 } else if (histogram_type == LINEAR) {
419 render_histogram = reinterpret_cast<Histogram*>
420 (new LinearHistogram(histogram_name.c_str(),
421 declared_min,
422 declared_max,
423 bucket_count));
424 } else {
425 LOG(ERROR) << "Error Deserializing Histogram Unknown histogram_type: " <<
426 histogram_type;
427 return false;
428 }
429 DCHECK(!(flags & kRendererHistogramFlag));
430 render_histogram->SetFlags(flags | kRendererHistogramFlag);
431 }
432
433 DCHECK(declared_min == render_histogram->declared_min());
434 DCHECK(declared_max == render_histogram->declared_max());
435 DCHECK(bucket_count == render_histogram->bucket_count());
436 DCHECK(histogram_type == render_histogram->histogram_type());
437
438 if (render_histogram->flags() & kRendererHistogramFlag) {
439 render_histogram->AddSampleSet(sample);
440 } else {
441 DLOG(INFO) << "Single thread mode, histogram observed and not copied: " <<
442 histogram_name;
443 }
444
445 return true;
446 }
447
448
352 //------------------------------------------------------------------------------ 449 //------------------------------------------------------------------------------
353 // Methods for the Histogram::SampleSet class 450 // Methods for the Histogram::SampleSet class
354 //------------------------------------------------------------------------------ 451 //------------------------------------------------------------------------------
355 452
356 Histogram::SampleSet::SampleSet() 453 Histogram::SampleSet::SampleSet()
357 : counts_(), 454 : counts_(),
358 sum_(0), 455 sum_(0),
359 square_sum_(0) { 456 square_sum_(0) {
360 } 457 }
361 458
(...skipping 14 matching lines...) Expand all
376 square_sum_ += (count * value) * static_cast<int64>(value); 473 square_sum_ += (count * value) * static_cast<int64>(value);
377 DCHECK(counts_[index] >= 0); 474 DCHECK(counts_[index] >= 0);
378 DCHECK(sum_ >= 0); 475 DCHECK(sum_ >= 0);
379 DCHECK(square_sum_ >= 0); 476 DCHECK(square_sum_ >= 0);
380 } 477 }
381 478
382 Count Histogram::SampleSet::TotalCount() const { 479 Count Histogram::SampleSet::TotalCount() const {
383 Count total = 0; 480 Count total = 0;
384 for (Counts::const_iterator it = counts_.begin(); 481 for (Counts::const_iterator it = counts_.begin();
385 it != counts_.end(); 482 it != counts_.end();
386 it++) { 483 ++it) {
387 total += *it; 484 total += *it;
388 } 485 }
389 return total; 486 return total;
390 } 487 }
391 488
392 void Histogram::SampleSet::Add(const SampleSet& other) { 489 void Histogram::SampleSet::Add(const SampleSet& other) {
393 DCHECK(counts_.size() == other.counts_.size()); 490 DCHECK(counts_.size() == other.counts_.size());
394 sum_ += other.sum_; 491 sum_ += other.sum_;
395 square_sum_ += other.square_sum_; 492 square_sum_ += other.square_sum_;
396 for (size_t index = 0; index < counts_.size(); index++) 493 for (size_t index = 0; index < counts_.size(); ++index)
397 counts_[index] += other.counts_[index]; 494 counts_[index] += other.counts_[index];
398 } 495 }
399 496
400 void Histogram::SampleSet::Subtract(const SampleSet& other) { 497 void Histogram::SampleSet::Subtract(const SampleSet& other) {
401 DCHECK(counts_.size() == other.counts_.size()); 498 DCHECK(counts_.size() == other.counts_.size());
402 // Note: Race conditions in snapshotting a sum or square_sum may lead to 499 // Note: Race conditions in snapshotting a sum or square_sum may lead to
403 // (temporary) negative values when snapshots are later combined (and deltas 500 // (temporary) negative values when snapshots are later combined (and deltas
404 // calculated). As a result, we don't currently CHCEK() for positive values. 501 // calculated). As a result, we don't currently CHCEK() for positive values.
405 sum_ -= other.sum_; 502 sum_ -= other.sum_;
406 square_sum_ -= other.square_sum_; 503 square_sum_ -= other.square_sum_;
407 for (size_t index = 0; index < counts_.size(); index++) { 504 for (size_t index = 0; index < counts_.size(); ++index) {
408 counts_[index] -= other.counts_[index]; 505 counts_[index] -= other.counts_[index];
409 DCHECK(counts_[index] >= 0); 506 DCHECK(counts_[index] >= 0);
410 } 507 }
411 } 508 }
412 509
510 bool Histogram::SampleSet::Serialize(Pickle* pickle) const {
511 pickle->WriteInt64(sum_);
512 pickle->WriteInt64(square_sum_);
513 pickle->WriteSize(counts_.size());
514
515 for (size_t index = 0; index < counts_.size(); ++index) {
516 pickle->WriteInt(counts_[index]);
517 }
518
519 return true;
520 }
521
522 bool Histogram::SampleSet::Deserialize(void** iter, const Pickle& pickle) {
523 DCHECK(counts_.size() == 0);
524 DCHECK(sum_ == 0);
525 DCHECK(square_sum_ == 0);
526
527 size_t counts_size;
528
529 if (!pickle.ReadInt64(iter, &sum_) ||
530 !pickle.ReadInt64(iter, &square_sum_) ||
531 !pickle.ReadSize(iter, &counts_size)) {
532 return false;
533 }
534
535 if (counts_size <= 0)
536 return false;
537
538 counts_.resize(counts_size, 0);
539 for (size_t index = 0; index < counts_size; ++index) {
540 if (!pickle.ReadInt(iter, &counts_[index])) {
541 return false;
542 }
543 }
544
545 return true;
546 }
547
413 //------------------------------------------------------------------------------ 548 //------------------------------------------------------------------------------
414 // LinearHistogram: This histogram uses a traditional set of evenly spaced 549 // LinearHistogram: This histogram uses a traditional set of evenly spaced
415 // buckets. 550 // buckets.
416 //------------------------------------------------------------------------------ 551 //------------------------------------------------------------------------------
417 552
418 LinearHistogram::LinearHistogram(const char* name, 553 LinearHistogram::LinearHistogram(const char* name, Sample minimum,
419 Sample minimum, Sample maximum, size_t bucket_count) 554 Sample maximum, size_t bucket_count)
420 : Histogram(name, minimum >= 1 ? minimum : 1, maximum, bucket_count) { 555 : Histogram(name, minimum >= 1 ? minimum : 1, maximum, bucket_count) {
421 InitializeBucketRange(); 556 InitializeBucketRange();
422 DCHECK(ValidateBucketRanges()); 557 DCHECK(ValidateBucketRanges());
423 } 558 }
424 559
425 LinearHistogram::LinearHistogram(const char* name, 560 LinearHistogram::LinearHistogram(const char* name,
426 TimeDelta minimum, TimeDelta maximum, size_t bucket_count) 561 TimeDelta minimum, TimeDelta maximum, size_t bucket_count)
427 : Histogram(name, minimum >= TimeDelta::FromMilliseconds(1) ? 562 : Histogram(name, minimum >= TimeDelta::FromMilliseconds(1) ?
428 minimum : TimeDelta::FromMilliseconds(1), 563 minimum : TimeDelta::FromMilliseconds(1),
429 maximum, bucket_count) { 564 maximum, bucket_count) {
(...skipping 20 matching lines...) Expand all
450 bool LinearHistogram::PrintEmptyBucket(size_t index) const { 585 bool LinearHistogram::PrintEmptyBucket(size_t index) const {
451 return bucket_description_.find(ranges(index)) == bucket_description_.end(); 586 return bucket_description_.find(ranges(index)) == bucket_description_.end();
452 } 587 }
453 588
454 589
455 void LinearHistogram::InitializeBucketRange() { 590 void LinearHistogram::InitializeBucketRange() {
456 DCHECK(0 < declared_min()); // 0 is the underflow bucket here. 591 DCHECK(0 < declared_min()); // 0 is the underflow bucket here.
457 double min = declared_min(); 592 double min = declared_min();
458 double max = declared_max(); 593 double max = declared_max();
459 size_t i; 594 size_t i;
460 for (i = 1; i < bucket_count(); i++) { 595 for (i = 1; i < bucket_count(); ++i) {
461 double linear_range = (min * (bucket_count() -1 - i) + max * (i - 1)) / 596 double linear_range = (min * (bucket_count() -1 - i) + max * (i - 1)) /
462 (bucket_count() - 2); 597 (bucket_count() - 2);
463 SetBucketRange(i, static_cast<int> (linear_range + 0.5)); 598 SetBucketRange(i, static_cast<int> (linear_range + 0.5));
464 } 599 }
465 } 600 }
466 601
467 // Find bucket to increment for sample value. 602 // Find bucket to increment for sample value.
468 size_t LinearHistogram::BucketIndex(Sample value) const { 603 size_t LinearHistogram::BucketIndex(Sample value) const {
469 if (value < declared_min()) return 0; 604 if (value < declared_min()) return 0;
470 if (value >= declared_max()) return bucket_count() - 1; 605 if (value >= declared_max()) return bucket_count() - 1;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
541 delete lock_; 676 delete lock_;
542 lock_ = NULL; 677 lock_ = NULL;
543 } 678 }
544 679
545 // static 680 // static
546 bool StatisticsRecorder::WasStarted() { 681 bool StatisticsRecorder::WasStarted() {
547 return NULL != histograms_; 682 return NULL != histograms_;
548 } 683 }
549 684
550 // static 685 // static
551 bool StatisticsRecorder::Register(const Histogram& histogram) { 686 bool StatisticsRecorder::Register(Histogram* histogram) {
552 if (!histograms_) 687 if (!histograms_)
553 return false; 688 return false;
554 const std::string name = histogram.histogram_name(); 689 const std::string name = histogram->histogram_name();
555 AutoLock auto_lock(*lock_); 690 AutoLock auto_lock(*lock_);
556 691
557 DCHECK(histograms_->end() == histograms_->find(name)) << name << " is already" 692 DCHECK(histograms_->end() == histograms_->find(name)) << name << " is already"
558 "registered as a histogram. Check for duplicate use of the name, or a " 693 "registered as a histogram. Check for duplicate use of the name, or a "
559 "race where a static initializer could be run by several threads."; 694 "race where a static initializer could be run by several threads.";
560 (*histograms_)[name] = &histogram; 695 (*histograms_)[name] = histogram;
561 return true; 696 return true;
562 } 697 }
563 698
564 // static 699 // static
565 void StatisticsRecorder::UnRegister(const Histogram& histogram) { 700 void StatisticsRecorder::UnRegister(Histogram* histogram) {
566 if (!histograms_) 701 if (!histograms_)
567 return; 702 return;
568 const std::string name = histogram.histogram_name(); 703 const std::string name = histogram->histogram_name();
569 AutoLock auto_lock(*lock_); 704 AutoLock auto_lock(*lock_);
570 DCHECK(histograms_->end() != histograms_->find(name)); 705 DCHECK(histograms_->end() != histograms_->find(name));
571 histograms_->erase(name); 706 histograms_->erase(name);
572 if (dump_on_exit_) { 707 if (dump_on_exit_) {
573 std::string output; 708 std::string output;
574 histogram.WriteAscii(true, "\n", &output); 709 histogram->WriteAscii(true, "\n", &output);
575 LOG(INFO) << output; 710 LOG(INFO) << output;
576 } 711 }
577 } 712 }
578 713
579 // static 714 // static
580 void StatisticsRecorder::WriteHTMLGraph(const std::string& query, 715 void StatisticsRecorder::WriteHTMLGraph(const std::string& query,
581 std::string* output) { 716 std::string* output) {
582 if (!histograms_) 717 if (!histograms_)
583 return; 718 return;
584 output->append("<html><head><title>About Histograms"); 719 output->append("<html><head><title>About Histograms");
585 if (!query.empty()) 720 if (!query.empty())
586 output->append(" - " + query); 721 output->append(" - " + query);
587 output->append("</title>" 722 output->append("</title>"
588 // We'd like the following no-cache... but it doesn't work. 723 // We'd like the following no-cache... but it doesn't work.
589 // "<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">" 724 // "<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">"
590 "</head><body>"); 725 "</head><body>");
591 726
592 Histograms snapshot; 727 Histograms snapshot;
593 GetSnapshot(query, &snapshot); 728 GetSnapshot(query, &snapshot);
594 for (Histograms::iterator it = snapshot.begin(); 729 for (Histograms::iterator it = snapshot.begin();
595 it != snapshot.end(); 730 it != snapshot.end();
596 it++) { 731 ++it) {
597 (*it)->WriteHTMLGraph(output); 732 (*it)->WriteHTMLGraph(output);
598 output->append("<br><hr><br>"); 733 output->append("<br><hr><br>");
599 } 734 }
600 output->append("</body></html>"); 735 output->append("</body></html>");
601 } 736 }
602 737
603 // static 738 // static
604 void StatisticsRecorder::WriteGraph(const std::string& query, 739 void StatisticsRecorder::WriteGraph(const std::string& query,
605 std::string* output) { 740 std::string* output) {
606 if (!histograms_) 741 if (!histograms_)
607 return; 742 return;
608 if (query.length()) 743 if (query.length())
609 StringAppendF(output, "Collections of histograms for %s\n", query.c_str()); 744 StringAppendF(output, "Collections of histograms for %s\n", query.c_str());
610 else 745 else
611 output->append("Collections of all histograms\n"); 746 output->append("Collections of all histograms\n");
612 747
613 Histograms snapshot; 748 Histograms snapshot;
614 GetSnapshot(query, &snapshot); 749 GetSnapshot(query, &snapshot);
615 for (Histograms::iterator it = snapshot.begin(); 750 for (Histograms::iterator it = snapshot.begin();
616 it != snapshot.end(); 751 it != snapshot.end();
617 it++) { 752 ++it) {
618 (*it)->WriteAscii(true, "\n", output); 753 (*it)->WriteAscii(true, "\n", output);
619 output->append("\n"); 754 output->append("\n");
620 } 755 }
621 } 756 }
622 757
623 // static 758 // static
624 void StatisticsRecorder::GetHistograms(Histograms* output) { 759 void StatisticsRecorder::GetHistograms(Histograms* output) {
625 if (!histograms_) 760 if (!histograms_)
626 return; 761 return;
627 AutoLock auto_lock(*lock_); 762 AutoLock auto_lock(*lock_);
628 for (HistogramMap::iterator it = histograms_->begin(); 763 for (HistogramMap::iterator it = histograms_->begin();
629 histograms_->end() != it; 764 histograms_->end() != it;
630 it++) { 765 ++it) {
631 output->push_back(it->second); 766 output->push_back(it->second);
632 } 767 }
633 } 768 }
634 769
770 Histogram* StatisticsRecorder::GetHistogram(const std::string& query) {
771 if (!histograms_)
772 return NULL;
773 AutoLock auto_lock(*lock_);
774 for (HistogramMap::iterator it = histograms_->begin();
775 histograms_->end() != it;
776 ++it) {
777 if (it->first.find(query) != std::string::npos)
778 return it->second;
779 }
780 return NULL;
781 }
782
635 // private static 783 // private static
636 void StatisticsRecorder::GetSnapshot(const std::string& query, 784 void StatisticsRecorder::GetSnapshot(const std::string& query,
637 Histograms* snapshot) { 785 Histograms* snapshot) {
638 AutoLock auto_lock(*lock_); 786 AutoLock auto_lock(*lock_);
639 for (HistogramMap::iterator it = histograms_->begin(); 787 for (HistogramMap::iterator it = histograms_->begin();
640 histograms_->end() != it; 788 histograms_->end() != it;
641 it++) { 789 ++it) {
642 if (it->first.find(query) != std::string::npos) 790 if (it->first.find(query) != std::string::npos)
643 snapshot->push_back(it->second); 791 snapshot->push_back(it->second);
644 } 792 }
645 } 793 }
646 794
647 // static 795 // static
648 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; 796 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL;
649 // static 797 // static
650 Lock* StatisticsRecorder::lock_ = NULL; 798 Lock* StatisticsRecorder::lock_ = NULL;
651 // static 799 // static
652 bool StatisticsRecorder::dump_on_exit_ = false; 800 bool StatisticsRecorder::dump_on_exit_ = false;
OLDNEW
« no previous file with comments | « base/histogram.h ('k') | chrome/browser/browser_about_handler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698