histogram.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Histogram is an object that aggregates statistics, and can summarize them in 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// various forms, including ASCII graphical, HTML, and numerically (as a 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// vector of numbers corresponding to each of the aggregating buckets). 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// See header file for details and examples. 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <math.h> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/alias.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/sample_vector.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/statistics_recorder.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/pickle.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_util.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stringprintf.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::string; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::vector; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ReadHistogramArguments(PickleIterator* iter, 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) string* histogram_name, 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int* flags, 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int* declared_min, 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int* declared_max, 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint64* bucket_count, 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32* range_checksum) { 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!iter->ReadString(histogram_name) || 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !iter->ReadInt(flags) || 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !iter->ReadInt(declared_min) || 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !iter->ReadInt(declared_max) || 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !iter->ReadUInt64(bucket_count) || 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !iter->ReadUInt32(range_checksum)) { 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DLOG(ERROR) << "Pickle error decoding Histogram: " << *histogram_name; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Since these fields may have come from an untrusted renderer, do additional 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // checks above and beyond those in Histogram::Initialize() 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (*declared_max <= 0 || 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *declared_min <= 0 || 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *declared_max < *declared_min || 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) INT_MAX / sizeof(HistogramBase::Count) <= *bucket_count || 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *bucket_count < 2) { 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DLOG(ERROR) << "Values error decoding Histogram: " << histogram_name; 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We use the arguments to find or create the local version of the histogram 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // in this process, so we need to clear the IPC flag. 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(*flags & HistogramBase::kIPCSerializationSourceFlag); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *flags &= ~HistogramBase::kIPCSerializationSourceFlag; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ValidateRangeChecksum(const HistogramBase& histogram, 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32 range_checksum) { 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Histogram& casted_histogram = 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<const Histogram&>(histogram); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return casted_histogram.bucket_ranges()->checksum() == range_checksum; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef HistogramBase::Count Count; 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef HistogramBase::Sample Sample; 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t Histogram::kBucketCount_MAX = 16384u; 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HistogramBase* Histogram::FactoryGet(const string& name, 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Sample minimum, 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Sample maximum, 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t bucket_count, 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 flags) { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool valid_arguments = 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InspectConstructionArguments(name, &minimum, &maximum, &bucket_count); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(valid_arguments); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!histogram) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To avoid racy destruction at shutdown, the following will be leaked. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BucketRanges* ranges = new BucketRanges(bucket_count + 1); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitializeBucketRanges(minimum, maximum, bucket_count, ranges); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BucketRanges* registered_ranges = 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Histogram* tentative_histogram = 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new Histogram(name, minimum, maximum, bucket_count, registered_ranges); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tentative_histogram->SetFlags(flags); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) histogram = 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(HISTOGRAM, histogram->GetHistogramType()); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(histogram->HasConstructionArguments(minimum, maximum, bucket_count)); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return histogram; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HistogramBase* Histogram::FactoryTimeGet(const string& name, 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TimeDelta minimum, 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TimeDelta maximum, 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t bucket_count, 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 flags) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FactoryGet(name, minimum.InMilliseconds(), maximum.InMilliseconds(), 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bucket_count, flags); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TimeTicks Histogram::DebugNow() { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TimeTicks::Now(); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TimeTicks(); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Calculate what range of values are held in each bucket. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We have to be careful that we don't pick a ratio between starting points in 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// consecutive buckets that is sooo small, that the integer bounds are the same 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (effectively making one bucket get no values). We need to avoid: 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ranges(i) == ranges(i + 1) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To avoid that, we just do a fine-grained bucket width as far as we need to 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// until we get a ratio that moves us along at least 2 units at a time. From 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that bucket onward we do use the exponential growth of buckets. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Histogram::InitializeBucketRanges(Sample minimum, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sample maximum, 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bucket_count, 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BucketRanges* ranges) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(ranges->size(), bucket_count + 1); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double log_max = log(static_cast<double>(maximum)); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double log_ratio; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double log_next; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bucket_index = 1; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sample current = minimum; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ranges->set_range(bucket_index, current); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (bucket_count > ++bucket_index) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double log_current; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log_current = log(static_cast<double>(current)); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Calculate the count'th root of the range. 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log_ratio = (log_max - log_current) / (bucket_count - bucket_index); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See where the next bucket would start. 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log_next = log_current + log_ratio; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sample next; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next = static_cast<int>(floor(exp(log_next) + 0.5)); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next > current) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current = next; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++current; // Just do a narrow bucket, and keep trying. 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ranges->set_range(bucket_index, current); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ranges->set_range(ranges->size() - 1, HistogramBase::kSampleType_MAX); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ranges->ResetChecksum(); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int Histogram::kCommonRaceBasedCountMismatch = 5; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int Histogram::FindCorruption(const HistogramSamples& samples) const { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int inconsistencies = NO_INCONSISTENCIES; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sample previous_range = -1; // Bottom range is always 0. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t index = 0; index < bucket_count(); ++index) { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int new_range = ranges(index); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (previous_range >= new_range) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inconsistencies |= BUCKET_ORDER_ERROR; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_range = new_range; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!bucket_ranges()->HasValidChecksum()) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inconsistencies |= RANGE_CHECKSUM_ERROR; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 delta64 = samples.redundant_count() - samples.TotalCount(); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delta64 != 0) { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int delta = static_cast<int>(delta64); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delta != delta64) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delta = INT_MAX; // Flag all giant errors as INT_MAX. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delta > 0) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("Histogram.InconsistentCountHigh", delta); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delta > kCommonRaceBasedCountMismatch) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inconsistencies |= COUNT_HIGH_ERROR; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(0, delta); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("Histogram.InconsistentCountLow", -delta); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (-delta > kCommonRaceBasedCountMismatch) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inconsistencies |= COUNT_LOW_ERROR; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return inconsistencies; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Sample Histogram::ranges(size_t i) const { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bucket_ranges_->range(i); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t Histogram::bucket_count() const { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bucket_count_; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Histogram::InspectConstructionArguments(const string& name, 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sample* minimum, 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sample* maximum, 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t* bucket_count) { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Defensive code for backward compatibility. 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*minimum < 1) { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Histogram: " << name << " has bad minimum: " << *minimum; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *minimum = 1; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*maximum >= kSampleType_MAX) { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Histogram: " << name << " has bad maximum: " << *maximum; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *maximum = kSampleType_MAX - 1; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*bucket_count >= kBucketCount_MAX) { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Histogram: " << name << " has bad bucket_count: " 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << *bucket_count; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *bucket_count = kBucketCount_MAX - 1; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*minimum >= *maximum) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*bucket_count < 3) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*bucket_count > static_cast<size_t>(*maximum - *minimum + 2)) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HistogramType Histogram::GetHistogramType() const { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HISTOGRAM; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Histogram::HasConstructionArguments(Sample minimum, 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sample maximum, 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bucket_count) const { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ((minimum == declared_min_) && (maximum == declared_max_) && 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (bucket_count == bucket_count_)); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Histogram::Add(int value) { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(0, ranges(0)); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(kSampleType_MAX, ranges(bucket_count_)); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (value > kSampleType_MAX - 1) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value = kSampleType_MAX - 1; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (value < 0) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value = 0; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) samples_->Accumulate(value, 1); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<HistogramSamples> Histogram::SnapshotSamples() const { 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SnapshotSampleVector().PassAs<HistogramSamples>(); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Histogram::AddSamples(const HistogramSamples& samples) { 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) samples_->Add(samples); 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Histogram::AddSamplesFromPickle(PickleIterator* iter) { 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return samples_->AddFromPickle(iter); 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following methods provide a graphical histogram display. 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Histogram::WriteHTMLGraph(string* output) const { 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TBD(jar) Write a nice HTML bar chart, with divs an mouse-overs etc. 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->append("<PRE>"); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteAsciiImpl(true, "<br>", output); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->append("</PRE>"); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Histogram::WriteAscii(string* output) const { 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteAsciiImpl(true, "\n", output); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Histogram::SerializeInfoImpl(Pickle* pickle) const { 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(bucket_ranges()->HasValidChecksum()); 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return pickle->WriteString(histogram_name()) && 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pickle->WriteInt(flags()) && 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pickle->WriteInt(declared_min()) && 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pickle->WriteInt(declared_max()) && 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pickle->WriteUInt64(bucket_count()) && 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pickle->WriteUInt32(bucket_ranges()->checksum()); 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Histogram::Histogram(const string& name, 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sample minimum, 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sample maximum, 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bucket_count, 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BucketRanges* ranges) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : HistogramBase(name), 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bucket_ranges_(ranges), 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) declared_min_(minimum), 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) declared_max_(maximum), 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bucket_count_(bucket_count) { 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ranges) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) samples_.reset(new SampleVector(ranges)); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Histogram::~Histogram() { 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Histogram::PrintEmptyBucket(size_t index) const { 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use the actual bucket widths (like a linear histogram) until the widths get 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// over some transition value, and then use that transition width. Exponentials 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// get so big so fast (and we don't expect to see a lot of entries in the large 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// buckets), so we need this to make it possible to see what is going on and 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not have 0-graphical-height buckets. 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double Histogram::GetBucketSize(Count current, size_t i) const { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(ranges(i + 1), ranges(i)); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const double kTransitionWidth = 5; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double denominator = ranges(i + 1) - ranges(i); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (denominator > kTransitionWidth) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) denominator = kTransitionWidth; // Stop trying to normalize. 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return current/denominator; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const string Histogram::GetAsciiBucketRange(size_t i) const { 338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GetSimpleAsciiBucketRange(ranges(i)); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Private methods 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HistogramBase* Histogram::DeserializeInfoImpl(PickleIterator* iter) { 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) string histogram_name; 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int flags; 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int declared_min; 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int declared_max; 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint64 bucket_count; 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32 range_checksum; 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &declared_max, &bucket_count, &range_checksum)) { 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Find or create the local version of the histogram in this process. 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HistogramBase* histogram = Histogram::FactoryGet( 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) histogram_name, declared_min, declared_max, bucket_count, flags); 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!ValidateRangeChecksum(*histogram, range_checksum)) { 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The serialized histogram might be corrupted. 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return histogram; 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<SampleVector> Histogram::SnapshotSampleVector() const { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<SampleVector> samples(new SampleVector(bucket_ranges())); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) samples->Add(*samples_); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return samples.Pass(); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Histogram::WriteAsciiImpl(bool graph_it, 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string& newline, 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string* output) const { 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get local (stack) copies of all effectively volatile class data so that we 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // are consistent across our output activities. 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<SampleVector> snapshot = SnapshotSampleVector(); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Count sample_count = snapshot->TotalCount(); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteAsciiHeader(*snapshot, sample_count, output); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->append(newline); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prepare to normalize graphical rendering of bucket contents. 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double max_size = 0; 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (graph_it) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_size = GetPeakBucketSize(*snapshot); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Calculate space needed to print bucket range numbers. Leave room to print 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // nearly the largest bucket range without sliding over the histogram. 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t largest_non_empty_bucket = bucket_count() - 1; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (0 == snapshot->GetCountAtIndex(largest_non_empty_bucket)) { 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (0 == largest_non_empty_bucket) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; // All buckets are empty. 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --largest_non_empty_bucket; 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Calculate largest print width needed for any of our bucket range displays. 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t print_width = 1; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < bucket_count(); ++i) { 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (snapshot->GetCountAtIndex(i)) { 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t width = GetAsciiBucketRange(i).size() + 1; 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (width > print_width) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print_width = width; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 remaining = sample_count; 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 past = 0; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Output the actual histogram graph. 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < bucket_count(); ++i) { 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Count current = snapshot->GetCountAtIndex(i); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!current && !PrintEmptyBucket(i)) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remaining -= current; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string range = GetAsciiBucketRange(i); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->append(range); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t j = 0; range.size() + j < print_width + 1; ++j) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->push_back(' '); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (0 == current && i < bucket_count() - 1 && 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0 == snapshot->GetCountAtIndex(i + 1)) { 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (i < bucket_count() - 1 && 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0 == snapshot->GetCountAtIndex(i + 1)) { 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->append("... "); 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->append(newline); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // No reason to plot emptiness. 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double current_size = GetBucketSize(current, i); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (graph_it) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteAsciiBucketGraph(current_size, max_size, output); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteAsciiBucketContext(past, current, remaining, i, output); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->append(newline); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) past += current; 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(sample_count, past); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double Histogram::GetPeakBucketSize(const SampleVector& samples) const { 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double max = 0; 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < bucket_count() ; ++i) { 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double current_size = GetBucketSize(samples.GetCountAtIndex(i), i); 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_size > max) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max = current_size; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return max; 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Histogram::WriteAsciiHeader(const SampleVector& samples, 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Count sample_count, 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string* output) const { 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringAppendF(output, 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Histogram: %s recorded %d samples", 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) histogram_name().c_str(), 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sample_count); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (0 == sample_count) { 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(samples.sum(), 0); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double average = static_cast<float>(samples.sum()) / sample_count; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringAppendF(output, ", average = %.1f", average); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (flags() & ~kHexRangePrintingFlag) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringAppendF(output, " (flags = 0x%x)", flags() & ~kHexRangePrintingFlag); 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Histogram::WriteAsciiBucketContext(const int64 past, 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Count current, 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int64 remaining, 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t i, 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string* output) const { 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double scaled_sum = (past + current + remaining) / 100.0; 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteAsciiBucketValue(current, scaled_sum, output); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (0 < i) { 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double percentage = past / scaled_sum; 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringAppendF(output, " {%3.1f%%}", percentage); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Histogram::GetParameters(DictionaryValue* params) const { 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params->SetString("type", HistogramTypeToString(GetHistogramType())); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params->SetInteger("min", declared_min()); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params->SetInteger("max", declared_max()); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params->SetInteger("bucket_count", static_cast<int>(bucket_count())); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Histogram::GetCountAndBucketData(Count* count, ListValue* buckets) const { 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<SampleVector> snapshot = SnapshotSampleVector(); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *count = snapshot->TotalCount(); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t index = 0; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < bucket_count(); ++i) { 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sample count = snapshot->GetCountAtIndex(i); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (count > 0) { 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<DictionaryValue> bucket_value(new DictionaryValue()); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bucket_value->SetInteger("low", ranges(i)); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i != bucket_count() - 1) 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bucket_value->SetInteger("high", ranges(i + 1)); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bucket_value->SetInteger("count", count); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buckets->Set(index, bucket_value.release()); 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++index; 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LinearHistogram: This histogram uses a traditional set of evenly spaced 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// buckets. 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LinearHistogram::~LinearHistogram() {} 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HistogramBase* LinearHistogram::FactoryGet(const string& name, 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Sample minimum, 5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Sample maximum, 5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t bucket_count, 5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 flags) { 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FactoryGetWithRangeDescription( 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name, minimum, maximum, bucket_count, flags, NULL); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HistogramBase* LinearHistogram::FactoryTimeGet(const string& name, 5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TimeDelta minimum, 5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TimeDelta maximum, 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t bucket_count, 5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 flags) { 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FactoryGet(name, minimum.InMilliseconds(), maximum.InMilliseconds(), 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bucket_count, flags); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HistogramBase* LinearHistogram::FactoryGetWithRangeDescription( 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& name, 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sample minimum, 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sample maximum, 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bucket_count, 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 flags, 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DescriptionPair descriptions[]) { 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool valid_arguments = Histogram::InspectConstructionArguments( 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name, &minimum, &maximum, &bucket_count); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(valid_arguments); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!histogram) { 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To avoid racy destruction at shutdown, the following will be leaked. 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BucketRanges* ranges = new BucketRanges(bucket_count + 1); 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitializeBucketRanges(minimum, maximum, bucket_count, ranges); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BucketRanges* registered_ranges = 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LinearHistogram* tentative_histogram = 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new LinearHistogram(name, minimum, maximum, bucket_count, 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registered_ranges); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set range descriptions. 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (descriptions) { 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; descriptions[i].description; ++i) { 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tentative_histogram->bucket_description_[descriptions[i].sample] = 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) descriptions[i].description; 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tentative_histogram->SetFlags(flags); 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) histogram = 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(LINEAR_HISTOGRAM, histogram->GetHistogramType()); 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(histogram->HasConstructionArguments(minimum, maximum, bucket_count)); 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return histogram; 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HistogramType LinearHistogram::GetHistogramType() const { 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LINEAR_HISTOGRAM; 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LinearHistogram::LinearHistogram(const string& name, 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sample minimum, 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sample maximum, 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bucket_count, 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BucketRanges* ranges) 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : Histogram(name, minimum, maximum, bucket_count, ranges) { 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double LinearHistogram::GetBucketSize(Count current, size_t i) const { 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(ranges(i + 1), ranges(i)); 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Adjacent buckets with different widths would have "surprisingly" many (few) 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // samples in a histogram if we didn't normalize this way. 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double denominator = ranges(i + 1) - ranges(i); 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return current/denominator; 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const string LinearHistogram::GetAsciiBucketRange(size_t i) const { 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int range = ranges(i); 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BucketDescriptionMap::const_iterator it = bucket_description_.find(range); 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it == bucket_description_.end()) 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Histogram::GetAsciiBucketRange(i); 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return it->second; 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool LinearHistogram::PrintEmptyBucket(size_t index) const { 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bucket_description_.find(ranges(index)) == bucket_description_.end(); 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LinearHistogram::InitializeBucketRanges(Sample minimum, 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sample maximum, 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bucket_count, 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BucketRanges* ranges) { 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(ranges->size(), bucket_count + 1); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double min = minimum; 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double max = maximum; 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t i; 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 1; i < bucket_count; ++i) { 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double linear_range = 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (min * (bucket_count -1 - i) + max * (i - 1)) / (bucket_count - 2); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ranges->set_range(i, static_cast<Sample>(linear_range + 0.5)); 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ranges->set_range(ranges->size() - 1, HistogramBase::kSampleType_MAX); 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ranges->ResetChecksum(); 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HistogramBase* LinearHistogram::DeserializeInfoImpl(PickleIterator* iter) { 6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) string histogram_name; 6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int flags; 6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int declared_min; 6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int declared_max; 6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint64 bucket_count; 6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32 range_checksum; 6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, 6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &declared_max, &bucket_count, &range_checksum)) { 6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HistogramBase* histogram = LinearHistogram::FactoryGet( 6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) histogram_name, declared_min, declared_max, bucket_count, flags); 6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!ValidateRangeChecksum(*histogram, range_checksum)) { 6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The serialized histogram might be corrupted. 6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return histogram; 6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This section provides implementation for BooleanHistogram. 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HistogramBase* BooleanHistogram::FactoryGet(const string& name, int32 flags) { 6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!histogram) { 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To avoid racy destruction at shutdown, the following will be leaked. 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BucketRanges* ranges = new BucketRanges(4); 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LinearHistogram::InitializeBucketRanges(1, 2, 3, ranges); 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BucketRanges* registered_ranges = 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BooleanHistogram* tentative_histogram = 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new BooleanHistogram(name, registered_ranges); 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tentative_histogram->SetFlags(flags); 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) histogram = 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(BOOLEAN_HISTOGRAM, histogram->GetHistogramType()); 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return histogram; 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HistogramType BooleanHistogram::GetHistogramType() const { 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return BOOLEAN_HISTOGRAM; 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BooleanHistogram::BooleanHistogram(const string& name, 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BucketRanges* ranges) 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : LinearHistogram(name, 1, 2, 3, ranges) {} 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HistogramBase* BooleanHistogram::DeserializeInfoImpl(PickleIterator* iter) { 6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) string histogram_name; 6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int flags; 6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int declared_min; 6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int declared_max; 6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint64 bucket_count; 6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32 range_checksum; 6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, 6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &declared_max, &bucket_count, &range_checksum)) { 6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HistogramBase* histogram = BooleanHistogram::FactoryGet( 6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) histogram_name, flags); 6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!ValidateRangeChecksum(*histogram, range_checksum)) { 6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The serialized histogram might be corrupted. 6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return histogram; 7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CustomHistogram: 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HistogramBase* CustomHistogram::FactoryGet(const string& name, 7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const vector<Sample>& custom_ranges, 7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 flags) { 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(ValidateCustomRanges(custom_ranges)); 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HistogramBase* histogram = StatisticsRecorder::FindHistogram(name); 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!histogram) { 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BucketRanges* ranges = CreateBucketRangesFromCustomRanges(custom_ranges); 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BucketRanges* registered_ranges = 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges); 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To avoid racy destruction at shutdown, the following will be leaked. 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CustomHistogram* tentative_histogram = 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new CustomHistogram(name, registered_ranges); 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tentative_histogram->SetFlags(flags); 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) histogram = 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(histogram->GetHistogramType(), CUSTOM_HISTOGRAM); 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return histogram; 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HistogramType CustomHistogram::GetHistogramType() const { 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CUSTOM_HISTOGRAM; 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)vector<Sample> CustomHistogram::ArrayToCustomRanges( 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Sample* values, size_t num_values) { 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vector<Sample> all_values; 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < num_values; ++i) { 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sample value = values[i]; 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) all_values.push_back(value); 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure that a guard bucket is added. If we end up with duplicate 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // values, FactoryGet will take care of removing them. 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) all_values.push_back(value + 1); 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return all_values; 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CustomHistogram::CustomHistogram(const string& name, 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BucketRanges* ranges) 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : Histogram(name, 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ranges->range(1), 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ranges->range(ranges->size() - 2), 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ranges->size() - 1, 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ranges) {} 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { 7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!Histogram::SerializeInfoImpl(pickle)) 7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't 7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // write them. 7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 1; i < bucket_ranges()->size() - 1; ++i) { 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pickle->WriteInt(bucket_ranges()->range(i))) 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)double CustomHistogram::GetBucketSize(Count current, size_t i) const { 7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 1; 7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HistogramBase* CustomHistogram::DeserializeInfoImpl(PickleIterator* iter) { 7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) string histogram_name; 7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int flags; 7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int declared_min; 7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int declared_max; 7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint64 bucket_count; 7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32 range_checksum; 7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, 7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &declared_max, &bucket_count, &range_checksum)) { 7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // First and last ranges are not serialized. 7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) vector<Sample> sample_ranges(bucket_count - 1); 7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < sample_ranges.size(); ++i) { 7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!iter->ReadInt(&sample_ranges[i])) 7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HistogramBase* histogram = CustomHistogram::FactoryGet( 7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) histogram_name, sample_ranges, flags); 7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!ValidateRangeChecksum(*histogram, range_checksum)) { 8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The serialized histogram might be corrupted. 8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return histogram; 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CustomHistogram::ValidateCustomRanges( 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const vector<Sample>& custom_ranges) { 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_valid_range = false; 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < custom_ranges.size(); i++) { 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sample sample = custom_ranges[i]; 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sample != 0) 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_valid_range = true; 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return has_valid_range; 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BucketRanges* CustomHistogram::CreateBucketRangesFromCustomRanges( 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const vector<Sample>& custom_ranges) { 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove the duplicates in the custom ranges array. 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vector<int> ranges = custom_ranges; 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ranges.push_back(0); // Ensure we have a zero value. 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ranges.push_back(HistogramBase::kSampleType_MAX); 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::sort(ranges.begin(), ranges.end()); 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ranges.erase(std::unique(ranges.begin(), ranges.end()), ranges.end()); 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BucketRanges* bucket_ranges = new BucketRanges(ranges.size()); 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < ranges.size(); i++) { 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bucket_ranges->set_range(i, ranges[i]); 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bucket_ranges->ResetChecksum(); 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bucket_ranges; 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 839