Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 #include "base/string_util.h" | 23 #include "base/string_util.h" |
| 24 #include "base/stringprintf.h" | 24 #include "base/stringprintf.h" |
| 25 #include "base/synchronization/lock.h" | 25 #include "base/synchronization/lock.h" |
| 26 #include "base/values.h" | 26 #include "base/values.h" |
| 27 | 27 |
| 28 using std::string; | 28 using std::string; |
| 29 using std::vector; | 29 using std::vector; |
| 30 | 30 |
| 31 namespace base { | 31 namespace base { |
| 32 | 32 |
| 33 namespace { | |
| 34 | |
| 35 bool ReadHistogramArguments(PickleIterator* iter, | |
| 36 string* histogram_name, | |
| 37 int* flags, | |
| 38 int* declared_min, | |
| 39 int* declared_max, | |
| 40 uint64* bucket_count, | |
| 41 uint32* range_checksum) { | |
| 42 if (!iter->ReadString(histogram_name) || | |
| 43 !iter->ReadInt(flags) || | |
| 44 !iter->ReadInt(declared_min) || | |
| 45 !iter->ReadInt(declared_max) || | |
| 46 !iter->ReadUInt64(bucket_count) || | |
| 47 !iter->ReadUInt32(range_checksum)) { | |
| 48 DLOG(ERROR) << "Pickle error decoding Histogram: " << *histogram_name; | |
| 49 return false; | |
| 50 } | |
| 51 | |
| 52 // Since these fields may have come from an untrusted renderer, do additional | |
| 53 // checks above and beyond those in Histogram::Initialize() | |
| 54 if (*declared_max <= 0 || | |
| 55 *declared_min <= 0 || | |
| 56 *declared_max < *declared_min || | |
| 57 INT_MAX / sizeof(HistogramBase::Count) <= *bucket_count || | |
| 58 *bucket_count < 2) { | |
| 59 DLOG(ERROR) << "Values error decoding Histogram: " << histogram_name; | |
| 60 return false; | |
| 61 } | |
| 62 | |
| 63 // We use the arguments to find or create the local version of the histogram | |
| 64 // in this process. So need to clear IPC flag first. | |
|
Ilya Sherman
2012/12/29 00:17:30
nit: "in this process. So need to clear IPC flag"
kaiwang
2013/01/08 00:51:40
Done.
| |
| 65 DCHECK(*flags & HistogramBase::kIPCSerializationSourceFlag); | |
| 66 *flags &= ~HistogramBase::kIPCSerializationSourceFlag; | |
| 67 | |
| 68 return true; | |
| 69 } | |
| 70 | |
| 71 bool ValidateRangeChecksum(const HistogramBase* histogram, | |
|
Ilya Sherman
2012/12/29 00:17:30
nit: Please pass by const-reference.
kaiwang
2013/01/08 00:51:40
Done.
| |
| 72 uint32 range_checksum) { | |
| 73 const Histogram* casted_histogram = | |
| 74 static_cast<const Histogram*>(histogram); | |
| 75 | |
| 76 return casted_histogram->bucket_ranges()->checksum() == range_checksum; | |
| 77 } | |
| 78 | |
| 79 } // namespace | |
| 80 | |
| 33 typedef HistogramBase::Count Count; | 81 typedef HistogramBase::Count Count; |
| 34 typedef HistogramBase::Sample Sample; | 82 typedef HistogramBase::Sample Sample; |
| 35 | 83 |
| 36 // static | 84 // static |
| 37 const size_t Histogram::kBucketCount_MAX = 16384u; | 85 const size_t Histogram::kBucketCount_MAX = 16384u; |
| 38 | 86 |
| 39 // TODO(rtenneti): delete this code after debugging. | 87 // TODO(rtenneti): delete this code after debugging. |
| 40 void CheckCorruption(const Histogram& histogram, bool new_histogram) { | 88 void CheckCorruption(const Histogram& histogram, bool new_histogram) { |
| 41 const std::string& histogram_name = histogram.histogram_name(); | 89 const std::string& histogram_name = histogram.histogram_name(); |
| 42 char histogram_name_buf[128]; | 90 char histogram_name_buf[128]; |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 146 ranges->set_range(bucket_index, current); | 194 ranges->set_range(bucket_index, current); |
| 147 } | 195 } |
| 148 ranges->set_range(ranges->size() - 1, HistogramBase::kSampleType_MAX); | 196 ranges->set_range(ranges->size() - 1, HistogramBase::kSampleType_MAX); |
| 149 ranges->ResetChecksum(); | 197 ranges->ResetChecksum(); |
| 150 } | 198 } |
| 151 | 199 |
| 152 void Histogram::AddBoolean(bool value) { | 200 void Histogram::AddBoolean(bool value) { |
| 153 DCHECK(false); | 201 DCHECK(false); |
| 154 } | 202 } |
| 155 | 203 |
| 156 void Histogram::AddSamples(const HistogramSamples& samples) { | |
| 157 samples_->Add(samples); | |
| 158 } | |
| 159 | |
| 160 bool Histogram::AddSamplesFromPickle(PickleIterator* iter) { | |
| 161 return samples_->AddFromPickle(iter); | |
| 162 } | |
| 163 | |
| 164 // static | |
| 165 string Histogram::SerializeHistogramInfo(const Histogram& histogram, | |
| 166 const HistogramSamples& snapshot) { | |
| 167 DCHECK(histogram.bucket_ranges()->HasValidChecksum()); | |
|
Ilya Sherman
2012/12/29 00:17:30
What happened to this DCHECK?
kaiwang
2013/01/08 00:51:40
Added to Histogram::SerializeInfoImpl
| |
| 168 | |
| 169 Pickle pickle; | |
| 170 pickle.WriteString(histogram.histogram_name()); | |
| 171 pickle.WriteInt(histogram.declared_min()); | |
| 172 pickle.WriteInt(histogram.declared_max()); | |
| 173 pickle.WriteUInt64(histogram.bucket_count()); | |
| 174 pickle.WriteUInt32(histogram.bucket_ranges()->checksum()); | |
| 175 pickle.WriteInt(histogram.GetHistogramType()); | |
| 176 pickle.WriteInt(histogram.flags()); | |
| 177 | |
| 178 histogram.SerializeRanges(&pickle); | |
| 179 | |
| 180 snapshot.Serialize(&pickle); | |
| 181 | |
| 182 return string(static_cast<const char*>(pickle.data()), pickle.size()); | |
| 183 } | |
| 184 | |
| 185 // static | |
| 186 bool Histogram::DeserializeHistogramInfo(const string& histogram_info) { | |
| 187 if (histogram_info.empty()) { | |
| 188 return false; | |
| 189 } | |
| 190 | |
| 191 Pickle pickle(histogram_info.data(), | |
| 192 static_cast<int>(histogram_info.size())); | |
| 193 string histogram_name; | |
| 194 int declared_min; | |
| 195 int declared_max; | |
| 196 uint64 bucket_count; | |
| 197 uint32 range_checksum; | |
| 198 int histogram_type; | |
| 199 int pickle_flags; | |
| 200 | |
| 201 PickleIterator iter(pickle); | |
| 202 if (!iter.ReadString(&histogram_name) || | |
| 203 !iter.ReadInt(&declared_min) || | |
| 204 !iter.ReadInt(&declared_max) || | |
| 205 !iter.ReadUInt64(&bucket_count) || | |
| 206 !iter.ReadUInt32(&range_checksum) || | |
| 207 !iter.ReadInt(&histogram_type) || | |
| 208 !iter.ReadInt(&pickle_flags)) { | |
| 209 DLOG(ERROR) << "Pickle error decoding Histogram: " << histogram_name; | |
| 210 return false; | |
| 211 } | |
| 212 | |
| 213 DCHECK(pickle_flags & kIPCSerializationSourceFlag); | |
| 214 // Since these fields may have come from an untrusted renderer, do additional | |
| 215 // checks above and beyond those in Histogram::Initialize() | |
| 216 if (declared_max <= 0 || declared_min <= 0 || declared_max < declared_min || | |
| 217 INT_MAX / sizeof(Count) <= bucket_count || bucket_count < 2) { | |
| 218 DLOG(ERROR) << "Values error decoding Histogram: " << histogram_name; | |
| 219 return false; | |
| 220 } | |
| 221 | |
| 222 Flags flags = static_cast<Flags>(pickle_flags & ~kIPCSerializationSourceFlag); | |
| 223 | |
| 224 Histogram* render_histogram(NULL); | |
| 225 | |
| 226 if (histogram_type == HISTOGRAM) { | |
| 227 render_histogram = Histogram::FactoryGet( | |
| 228 histogram_name, declared_min, declared_max, bucket_count, flags); | |
| 229 } else if (histogram_type == LINEAR_HISTOGRAM) { | |
| 230 render_histogram = LinearHistogram::FactoryGet( | |
| 231 histogram_name, declared_min, declared_max, bucket_count, flags); | |
| 232 } else if (histogram_type == BOOLEAN_HISTOGRAM) { | |
| 233 render_histogram = BooleanHistogram::FactoryGet(histogram_name, flags); | |
| 234 } else if (histogram_type == CUSTOM_HISTOGRAM) { | |
| 235 vector<Sample> sample_ranges(bucket_count); | |
| 236 if (!CustomHistogram::DeserializeRanges(&iter, &sample_ranges)) { | |
| 237 DLOG(ERROR) << "Pickle error decoding ranges: " << histogram_name; | |
| 238 return false; | |
| 239 } | |
| 240 render_histogram = | |
| 241 CustomHistogram::FactoryGet(histogram_name, sample_ranges, flags); | |
| 242 } else { | |
| 243 DLOG(ERROR) << "Error Deserializing Histogram Unknown histogram_type: " | |
| 244 << histogram_type; | |
| 245 return false; | |
| 246 } | |
| 247 | |
| 248 DCHECK_EQ(render_histogram->declared_min(), declared_min); | |
| 249 DCHECK_EQ(render_histogram->declared_max(), declared_max); | |
| 250 DCHECK_EQ(render_histogram->bucket_count(), bucket_count); | |
| 251 DCHECK_EQ(render_histogram->GetHistogramType(), histogram_type); | |
| 252 | |
| 253 if (render_histogram->bucket_ranges()->checksum() != range_checksum) { | |
| 254 return false; | |
| 255 } | |
| 256 | |
| 257 if (render_histogram->flags() & kIPCSerializationSourceFlag) { | |
| 258 DVLOG(1) << "Single process mode, histogram observed and not copied: " | |
| 259 << histogram_name; | |
| 260 return true; | |
| 261 } | |
| 262 | |
| 263 DCHECK_EQ(flags & render_histogram->flags(), flags); | |
|
Ilya Sherman
2012/12/29 00:17:30
nit: What happened to this DCHECK?
kaiwang
2013/01/08 00:51:40
Actually I really don't understand what's this DCH
Ilya Sherman
2013/01/08 22:31:53
I'm also not sure; perhaps Jim can comment? I thi
| |
| 264 return render_histogram->AddSamplesFromPickle(&iter); | |
| 265 } | |
| 266 | |
| 267 // static | 204 // static |
| 268 const int Histogram::kCommonRaceBasedCountMismatch = 5; | 205 const int Histogram::kCommonRaceBasedCountMismatch = 5; |
| 269 | 206 |
| 270 Histogram::Inconsistencies Histogram::FindCorruption( | 207 Histogram::Inconsistencies Histogram::FindCorruption( |
| 271 const HistogramSamples& samples) const { | 208 const HistogramSamples& samples) const { |
| 272 int inconsistencies = NO_INCONSISTENCIES; | 209 int inconsistencies = NO_INCONSISTENCIES; |
| 273 Sample previous_range = -1; // Bottom range is always 0. | 210 Sample previous_range = -1; // Bottom range is always 0. |
| 274 for (size_t index = 0; index < bucket_count(); ++index) { | 211 for (size_t index = 0; index < bucket_count(); ++index) { |
| 275 int new_range = ranges(index); | 212 int new_range = ranges(index); |
| 276 if (previous_range >= new_range) | 213 if (previous_range >= new_range) |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 356 value = kSampleType_MAX - 1; | 293 value = kSampleType_MAX - 1; |
| 357 if (value < 0) | 294 if (value < 0) |
| 358 value = 0; | 295 value = 0; |
| 359 samples_->Accumulate(value, 1); | 296 samples_->Accumulate(value, 1); |
| 360 } | 297 } |
| 361 | 298 |
| 362 scoped_ptr<HistogramSamples> Histogram::SnapshotSamples() const { | 299 scoped_ptr<HistogramSamples> Histogram::SnapshotSamples() const { |
| 363 return SnapshotSampleVector().PassAs<HistogramSamples>(); | 300 return SnapshotSampleVector().PassAs<HistogramSamples>(); |
| 364 } | 301 } |
| 365 | 302 |
| 303 void Histogram::AddSamples(const HistogramSamples& samples) { | |
| 304 samples_->Add(samples); | |
| 305 } | |
| 306 | |
| 307 bool Histogram::AddSamplesFromPickle(PickleIterator* iter) { | |
| 308 return samples_->AddFromPickle(iter); | |
| 309 } | |
| 310 | |
| 366 // The following methods provide a graphical histogram display. | 311 // The following methods provide a graphical histogram display. |
| 367 void Histogram::WriteHTMLGraph(string* output) const { | 312 void Histogram::WriteHTMLGraph(string* output) const { |
| 368 // TBD(jar) Write a nice HTML bar chart, with divs an mouse-overs etc. | 313 // TBD(jar) Write a nice HTML bar chart, with divs an mouse-overs etc. |
| 369 output->append("<PRE>"); | 314 output->append("<PRE>"); |
| 370 WriteAsciiImpl(true, "<br>", output); | 315 WriteAsciiImpl(true, "<br>", output); |
| 371 output->append("</PRE>"); | 316 output->append("</PRE>"); |
| 372 } | 317 } |
| 373 | 318 |
| 374 void Histogram::WriteAscii(string* output) const { | 319 void Histogram::WriteAscii(string* output) const { |
| 375 WriteAsciiImpl(true, "\n", output); | 320 WriteAsciiImpl(true, "\n", output); |
| 376 } | 321 } |
| 377 | 322 |
| 323 bool Histogram::SerializeInfoImpl(Pickle* pickle) const { | |
| 324 if (pickle->WriteString(histogram_name()) && | |
| 325 pickle->WriteInt(flags()) && | |
|
Ilya Sherman
2012/12/29 00:17:30
I'm curious, why did you move flags to be written
kaiwang
2013/01/08 00:51:40
histogram_name and flags are fields from Histogram
| |
| 326 pickle->WriteInt(declared_min()) && | |
| 327 pickle->WriteInt(declared_max()) && | |
| 328 pickle->WriteUInt64(bucket_count()) && | |
| 329 pickle->WriteUInt32(bucket_ranges()->checksum())) { | |
| 330 return true; | |
| 331 } | |
| 332 return false; | |
|
Ilya Sherman
2012/12/29 00:17:30
Optional nit: IMO it's tidier to write this as
re
kaiwang
2013/01/08 00:51:40
Done.
| |
| 333 } | |
| 334 | |
| 378 Histogram::Histogram(const string& name, | 335 Histogram::Histogram(const string& name, |
| 379 Sample minimum, | 336 Sample minimum, |
| 380 Sample maximum, | 337 Sample maximum, |
| 381 size_t bucket_count, | 338 size_t bucket_count, |
| 382 const BucketRanges* ranges) | 339 const BucketRanges* ranges) |
| 383 : HistogramBase(name), | 340 : HistogramBase(name), |
| 384 bucket_ranges_(ranges), | 341 bucket_ranges_(ranges), |
| 385 declared_min_(minimum), | 342 declared_min_(minimum), |
| 386 declared_max_(maximum), | 343 declared_max_(maximum), |
| 387 bucket_count_(bucket_count) { | 344 bucket_count_(bucket_count) { |
| 388 if (ranges) | 345 if (ranges) |
| 389 samples_.reset(new SampleVector(ranges)); | 346 samples_.reset(new SampleVector(ranges)); |
| 390 } | 347 } |
| 391 | 348 |
| 392 Histogram::~Histogram() { | 349 Histogram::~Histogram() { |
| 393 if (StatisticsRecorder::dump_on_exit()) { | 350 if (StatisticsRecorder::dump_on_exit()) { |
| 394 string output; | 351 string output; |
| 395 WriteAsciiImpl(true, "\n", &output); | 352 WriteAsciiImpl(true, "\n", &output); |
| 396 DLOG(INFO) << output; | 353 DLOG(INFO) << output; |
| 397 } | 354 } |
| 398 } | 355 } |
| 399 | 356 |
| 400 bool Histogram::SerializeRanges(Pickle* pickle) const { | |
| 401 return true; | |
| 402 } | |
| 403 | |
| 404 bool Histogram::PrintEmptyBucket(size_t index) const { | 357 bool Histogram::PrintEmptyBucket(size_t index) const { |
| 405 return true; | 358 return true; |
| 406 } | 359 } |
| 407 | 360 |
| 408 // Use the actual bucket widths (like a linear histogram) until the widths get | 361 // Use the actual bucket widths (like a linear histogram) until the widths get |
| 409 // over some transition value, and then use that transition width. Exponentials | 362 // over some transition value, and then use that transition width. Exponentials |
| 410 // get so big so fast (and we don't expect to see a lot of entries in the large | 363 // get so big so fast (and we don't expect to see a lot of entries in the large |
| 411 // buckets), so we need this to make it possible to see what is going on and | 364 // buckets), so we need this to make it possible to see what is going on and |
| 412 // not have 0-graphical-height buckets. | 365 // not have 0-graphical-height buckets. |
| 413 double Histogram::GetBucketSize(Count current, size_t i) const { | 366 double Histogram::GetBucketSize(Count current, size_t i) const { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 424 if (kHexRangePrintingFlag & flags()) | 377 if (kHexRangePrintingFlag & flags()) |
| 425 StringAppendF(&result, "%#x", ranges(i)); | 378 StringAppendF(&result, "%#x", ranges(i)); |
| 426 else | 379 else |
| 427 StringAppendF(&result, "%d", ranges(i)); | 380 StringAppendF(&result, "%d", ranges(i)); |
| 428 return result; | 381 return result; |
| 429 } | 382 } |
| 430 | 383 |
| 431 //------------------------------------------------------------------------------ | 384 //------------------------------------------------------------------------------ |
| 432 // Private methods | 385 // Private methods |
| 433 | 386 |
| 387 // static | |
| 388 HistogramBase* Histogram::DeserializeHistogramInfo(PickleIterator* iter) { | |
| 389 string histogram_name; | |
| 390 int flags; | |
| 391 int declared_min; | |
| 392 int declared_max; | |
| 393 uint64 bucket_count; | |
| 394 uint32 range_checksum; | |
| 395 | |
| 396 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, | |
| 397 &declared_max, &bucket_count, &range_checksum)) { | |
| 398 return NULL; | |
| 399 } | |
| 400 | |
| 401 // Find or create the local version of the histogram in this process. | |
| 402 HistogramBase* histogram = Histogram::FactoryGet( | |
| 403 histogram_name, declared_min, declared_max, bucket_count, flags); | |
| 404 | |
| 405 if (!ValidateRangeChecksum(histogram, range_checksum)) { | |
| 406 // The serialized histogram might be corrupted. | |
| 407 return NULL; | |
| 408 } | |
| 409 return histogram; | |
| 410 } | |
| 411 | |
| 434 scoped_ptr<SampleVector> Histogram::SnapshotSampleVector() const { | 412 scoped_ptr<SampleVector> Histogram::SnapshotSampleVector() const { |
| 435 scoped_ptr<SampleVector> samples(new SampleVector(bucket_ranges())); | 413 scoped_ptr<SampleVector> samples(new SampleVector(bucket_ranges())); |
| 436 samples->Add(*samples_); | 414 samples->Add(*samples_); |
| 437 return samples.Pass(); | 415 return samples.Pass(); |
| 438 } | 416 } |
| 439 | 417 |
| 440 void Histogram::WriteAsciiImpl(bool graph_it, | 418 void Histogram::WriteAsciiImpl(bool graph_it, |
| 441 const string& newline, | 419 const string& newline, |
| 442 string* output) const { | 420 string* output) const { |
| 443 // Get local (stack) copies of all effectively volatile class data so that we | 421 // Get local (stack) copies of all effectively volatile class data so that we |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 703 size_t i; | 681 size_t i; |
| 704 for (i = 1; i < bucket_count; ++i) { | 682 for (i = 1; i < bucket_count; ++i) { |
| 705 double linear_range = | 683 double linear_range = |
| 706 (min * (bucket_count -1 - i) + max * (i - 1)) / (bucket_count - 2); | 684 (min * (bucket_count -1 - i) + max * (i - 1)) / (bucket_count - 2); |
| 707 ranges->set_range(i, static_cast<Sample>(linear_range + 0.5)); | 685 ranges->set_range(i, static_cast<Sample>(linear_range + 0.5)); |
| 708 } | 686 } |
| 709 ranges->set_range(ranges->size() - 1, HistogramBase::kSampleType_MAX); | 687 ranges->set_range(ranges->size() - 1, HistogramBase::kSampleType_MAX); |
| 710 ranges->ResetChecksum(); | 688 ranges->ResetChecksum(); |
| 711 } | 689 } |
| 712 | 690 |
| 691 // static | |
| 692 HistogramBase* LinearHistogram::DeserializeHistogramInfo(PickleIterator* iter) { | |
| 693 string histogram_name; | |
| 694 int flags; | |
| 695 int declared_min; | |
| 696 int declared_max; | |
| 697 uint64 bucket_count; | |
| 698 uint32 range_checksum; | |
| 699 | |
| 700 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, | |
| 701 &declared_max, &bucket_count, &range_checksum)) { | |
| 702 return NULL; | |
| 703 } | |
| 704 | |
| 705 HistogramBase* histogram = LinearHistogram::FactoryGet( | |
| 706 histogram_name, declared_min, declared_max, bucket_count, flags); | |
| 707 if (!ValidateRangeChecksum(histogram, range_checksum)) { | |
| 708 // The serialized histogram might be corrupted. | |
| 709 return NULL; | |
| 710 } | |
| 711 return histogram; | |
| 712 } | |
| 713 | |
| 713 //------------------------------------------------------------------------------ | 714 //------------------------------------------------------------------------------ |
| 714 // This section provides implementation for BooleanHistogram. | 715 // This section provides implementation for BooleanHistogram. |
| 715 //------------------------------------------------------------------------------ | 716 //------------------------------------------------------------------------------ |
| 716 | 717 |
| 717 Histogram* BooleanHistogram::FactoryGet(const string& name, int32 flags) { | 718 Histogram* BooleanHistogram::FactoryGet(const string& name, int32 flags) { |
| 718 Histogram* histogram = StatisticsRecorder::FindHistogram(name); | 719 Histogram* histogram = StatisticsRecorder::FindHistogram(name); |
| 719 if (!histogram) { | 720 if (!histogram) { |
| 720 // To avoid racy destruction at shutdown, the following will be leaked. | 721 // To avoid racy destruction at shutdown, the following will be leaked. |
| 721 BucketRanges* ranges = new BucketRanges(4); | 722 BucketRanges* ranges = new BucketRanges(4); |
| 722 LinearHistogram::InitializeBucketRanges(1, 2, 3, ranges); | 723 LinearHistogram::InitializeBucketRanges(1, 2, 3, ranges); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 743 } | 744 } |
| 744 | 745 |
| 745 void BooleanHistogram::AddBoolean(bool value) { | 746 void BooleanHistogram::AddBoolean(bool value) { |
| 746 Add(value ? 1 : 0); | 747 Add(value ? 1 : 0); |
| 747 } | 748 } |
| 748 | 749 |
| 749 BooleanHistogram::BooleanHistogram(const string& name, | 750 BooleanHistogram::BooleanHistogram(const string& name, |
| 750 const BucketRanges* ranges) | 751 const BucketRanges* ranges) |
| 751 : LinearHistogram(name, 1, 2, 3, ranges) {} | 752 : LinearHistogram(name, 1, 2, 3, ranges) {} |
| 752 | 753 |
| 754 HistogramBase* BooleanHistogram::DeserializeHistogramInfo( | |
| 755 PickleIterator* iter) { | |
| 756 string histogram_name; | |
| 757 int flags; | |
| 758 int declared_min; | |
| 759 int declared_max; | |
| 760 uint64 bucket_count; | |
| 761 uint32 range_checksum; | |
| 762 | |
| 763 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, | |
| 764 &declared_max, &bucket_count, &range_checksum)) { | |
| 765 return NULL; | |
| 766 } | |
| 767 | |
| 768 HistogramBase* histogram = BooleanHistogram::FactoryGet( | |
| 769 histogram_name, flags); | |
| 770 if (!ValidateRangeChecksum(histogram, range_checksum)) { | |
| 771 // The serialized histogram might be corrupted. | |
| 772 return NULL; | |
| 773 } | |
| 774 return histogram; | |
| 775 } | |
|
Ilya Sherman
2012/12/29 00:17:30
It would be good to share more of this code, rathe
kaiwang
2013/01/08 00:51:40
I think the good thing of current code is it distr
Ilya Sherman
2013/01/08 22:31:53
I'm not convinced that this is true: HistogramBase
| |
| 776 | |
| 753 //------------------------------------------------------------------------------ | 777 //------------------------------------------------------------------------------ |
| 754 // CustomHistogram: | 778 // CustomHistogram: |
| 755 //------------------------------------------------------------------------------ | 779 //------------------------------------------------------------------------------ |
| 756 | 780 |
| 757 Histogram* CustomHistogram::FactoryGet(const string& name, | 781 Histogram* CustomHistogram::FactoryGet(const string& name, |
| 758 const vector<Sample>& custom_ranges, | 782 const vector<Sample>& custom_ranges, |
| 759 int32 flags) { | 783 int32 flags) { |
| 760 CHECK(ValidateCustomRanges(custom_ranges)); | 784 CHECK(ValidateCustomRanges(custom_ranges)); |
| 761 | 785 |
| 762 Histogram* histogram = StatisticsRecorder::FindHistogram(name); | 786 Histogram* histogram = StatisticsRecorder::FindHistogram(name); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 802 } | 826 } |
| 803 | 827 |
| 804 CustomHistogram::CustomHistogram(const string& name, | 828 CustomHistogram::CustomHistogram(const string& name, |
| 805 const BucketRanges* ranges) | 829 const BucketRanges* ranges) |
| 806 : Histogram(name, | 830 : Histogram(name, |
| 807 ranges->range(1), | 831 ranges->range(1), |
| 808 ranges->range(ranges->size() - 2), | 832 ranges->range(ranges->size() - 2), |
| 809 ranges->size() - 1, | 833 ranges->size() - 1, |
| 810 ranges) {} | 834 ranges) {} |
| 811 | 835 |
| 812 bool CustomHistogram::SerializeRanges(Pickle* pickle) const { | 836 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { |
| 813 for (size_t i = 0; i < bucket_ranges()->size(); ++i) { | 837 if (!Histogram::SerializeInfoImpl(pickle)) |
| 838 return false; | |
| 839 | |
| 840 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't | |
| 841 // write them. | |
| 842 for (size_t i = 1; i < bucket_ranges()->size() - 1; ++i) { | |
| 814 if (!pickle->WriteInt(bucket_ranges()->range(i))) | 843 if (!pickle->WriteInt(bucket_ranges()->range(i))) |
| 815 return false; | 844 return false; |
| 816 } | 845 } |
| 817 return true; | 846 return true; |
| 818 } | 847 } |
| 819 | 848 |
| 820 // static | |
| 821 bool CustomHistogram::DeserializeRanges( | |
| 822 PickleIterator* iter, vector<Sample>* ranges) { | |
| 823 for (size_t i = 0; i < ranges->size(); ++i) { | |
| 824 if (!iter->ReadInt(&(*ranges)[i])) | |
| 825 return false; | |
| 826 } | |
| 827 return true; | |
| 828 } | |
| 829 | |
| 830 double CustomHistogram::GetBucketSize(Count current, size_t i) const { | 849 double CustomHistogram::GetBucketSize(Count current, size_t i) const { |
| 831 return 1; | 850 return 1; |
| 832 } | 851 } |
| 833 | 852 |
| 834 // static | 853 // static |
| 854 HistogramBase* CustomHistogram::DeserializeHistogramInfo(PickleIterator* iter) { | |
| 855 string histogram_name; | |
| 856 int flags; | |
| 857 int declared_min; | |
| 858 int declared_max; | |
| 859 uint64 bucket_count; | |
| 860 uint32 range_checksum; | |
| 861 | |
| 862 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, | |
| 863 &declared_max, &bucket_count, &range_checksum)) { | |
| 864 return NULL; | |
| 865 } | |
| 866 | |
| 867 // First and last ranges are not serialized. | |
| 868 vector<Sample> sample_ranges(bucket_count - 1); | |
| 869 | |
| 870 for (size_t i = 0; i < sample_ranges.size(); ++i) { | |
| 871 if (!iter->ReadInt(&sample_ranges[i])) | |
| 872 return NULL; | |
| 873 } | |
| 874 | |
| 875 HistogramBase* histogram = CustomHistogram::FactoryGet( | |
| 876 histogram_name, sample_ranges, flags); | |
| 877 if (!ValidateRangeChecksum(histogram, range_checksum)) { | |
| 878 // The serialized histogram might be corrupted. | |
| 879 return NULL; | |
| 880 } | |
| 881 return histogram; | |
| 882 } | |
| 883 | |
| 884 // static | |
| 835 bool CustomHistogram::ValidateCustomRanges( | 885 bool CustomHistogram::ValidateCustomRanges( |
| 836 const vector<Sample>& custom_ranges) { | 886 const vector<Sample>& custom_ranges) { |
| 837 bool has_valid_range = false; | 887 bool has_valid_range = false; |
| 838 for (size_t i = 0; i < custom_ranges.size(); i++) { | 888 for (size_t i = 0; i < custom_ranges.size(); i++) { |
| 839 Sample sample = custom_ranges[i]; | 889 Sample sample = custom_ranges[i]; |
| 840 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) | 890 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) |
| 841 return false; | 891 return false; |
| 842 if (sample != 0) | 892 if (sample != 0) |
| 843 has_valid_range = true; | 893 has_valid_range = true; |
| 844 } | 894 } |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 857 | 907 |
| 858 BucketRanges* bucket_ranges = new BucketRanges(ranges.size()); | 908 BucketRanges* bucket_ranges = new BucketRanges(ranges.size()); |
| 859 for (size_t i = 0; i < ranges.size(); i++) { | 909 for (size_t i = 0; i < ranges.size(); i++) { |
| 860 bucket_ranges->set_range(i, ranges[i]); | 910 bucket_ranges->set_range(i, ranges[i]); |
| 861 } | 911 } |
| 862 bucket_ranges->ResetChecksum(); | 912 bucket_ranges->ResetChecksum(); |
| 863 return bucket_ranges; | 913 return bucket_ranges; |
| 864 } | 914 } |
| 865 | 915 |
| 866 } // namespace base | 916 } // namespace base |
| OLD | NEW |