| 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 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 }; | 147 }; |
| 148 | 148 |
| 149 HistogramBase* Histogram::Factory::Build() { | 149 HistogramBase* Histogram::Factory::Build() { |
| 150 // Import histograms from known persistent storage. Histograms could have | 150 // Import histograms from known persistent storage. Histograms could have |
| 151 // been added by other processes and they must be fetched and recognized | 151 // been added by other processes and they must be fetched and recognized |
| 152 // locally in order to be found by FindHistograms() below. If the persistent | 152 // locally in order to be found by FindHistograms() below. If the persistent |
| 153 // memory segment is not shared between processes, this call does nothing. | 153 // memory segment is not shared between processes, this call does nothing. |
| 154 ImportPersistentHistograms(); | 154 ImportPersistentHistograms(); |
| 155 | 155 |
| 156 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name_); | 156 HistogramBase* histogram = StatisticsRecorder::FindHistogram(name_); |
| 157 | |
| 158 // crbug.com/588946 debugging. See comment at end of function. | |
| 159 const BucketRanges* created_ranges = | |
| 160 reinterpret_cast<const BucketRanges*>(0xDEADBEEF); | |
| 161 const BucketRanges* registered_ranges = | |
| 162 reinterpret_cast<const BucketRanges*>(0xDEADBEEF); | |
| 163 HistogramBase* tentative_histogram = | |
| 164 reinterpret_cast<HistogramBase*>(0xDEADBEEF); | |
| 165 PersistentMemoryAllocator* allocator = | |
| 166 reinterpret_cast<PersistentMemoryAllocator*>(0xDEADBEEF); | |
| 167 PersistentMemoryAllocator::Reference histogram_ref = 0xDEADBEEF; | |
| 168 | |
| 169 if (!histogram) { | 157 if (!histogram) { |
| 170 // To avoid racy destruction at shutdown, the following will be leaked. | 158 // To avoid racy destruction at shutdown, the following will be leaked. |
| 171 created_ranges = CreateRanges(); | 159 const BucketRanges* created_ranges = CreateRanges(); |
| 172 registered_ranges = | 160 const BucketRanges* registered_ranges = |
| 173 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(created_ranges); | 161 StatisticsRecorder::RegisterOrDeleteDuplicateRanges(created_ranges); |
| 174 | 162 |
| 175 // In most cases, the bucket-count, minimum, and maximum values are known | 163 // In most cases, the bucket-count, minimum, and maximum values are known |
| 176 // when the code is written and so are passed in explicitly. In other | 164 // when the code is written and so are passed in explicitly. In other |
| 177 // cases (such as with a CustomHistogram), they are calculated dynamically | 165 // cases (such as with a CustomHistogram), they are calculated dynamically |
| 178 // at run-time. In the latter case, those ctor parameters are zero and | 166 // at run-time. In the latter case, those ctor parameters are zero and |
| 179 // the results extracted from the result of CreateRanges(). | 167 // the results extracted from the result of CreateRanges(). |
| 180 if (bucket_count_ == 0) { | 168 if (bucket_count_ == 0) { |
| 181 bucket_count_ = static_cast<uint32_t>(registered_ranges->bucket_count()); | 169 bucket_count_ = static_cast<uint32_t>(registered_ranges->bucket_count()); |
| 182 minimum_ = registered_ranges->range(1); | 170 minimum_ = registered_ranges->range(1); |
| 183 maximum_ = registered_ranges->range(bucket_count_ - 1); | 171 maximum_ = registered_ranges->range(bucket_count_ - 1); |
| 184 } | 172 } |
| 185 | 173 |
| 186 // Try to create the histogram using a "persistent" allocator. As of | 174 // Try to create the histogram using a "persistent" allocator. As of |
| 187 // 2015-01-14, the availability of such is controlled by a base::Feature | 175 // 2015-01-14, the availability of such is controlled by a base::Feature |
| 188 // that is off by default. If the allocator doesn't exist or if | 176 // that is off by default. If the allocator doesn't exist or if |
| 189 // allocating from it fails, code below will allocate the histogram from | 177 // allocating from it fails, code below will allocate the histogram from |
| 190 // the process heap. | 178 // the process heap. |
| 191 histogram_ref = 0; | 179 PersistentMemoryAllocator::Reference histogram_ref = 0; |
| 192 tentative_histogram = nullptr; | 180 HistogramBase* tentative_histogram = nullptr; |
| 193 allocator = | 181 PersistentMemoryAllocator* allocator = |
| 194 GetPersistentHistogramMemoryAllocator(); | 182 GetPersistentHistogramMemoryAllocator(); |
| 195 if (allocator) { | 183 if (allocator) { |
| 196 flags_ |= HistogramBase::kIsPersistent; | 184 flags_ |= HistogramBase::kIsPersistent; |
| 197 tentative_histogram = AllocatePersistentHistogram( | 185 tentative_histogram = AllocatePersistentHistogram( |
| 198 allocator, | 186 allocator, |
| 199 histogram_type_, | 187 histogram_type_, |
| 200 name_, | 188 name_, |
| 201 minimum_, | 189 minimum_, |
| 202 maximum_, | 190 maximum_, |
| 203 registered_ranges, | 191 registered_ranges, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 219 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); | 207 StatisticsRecorder::RegisterOrDeleteDuplicate(tentative_histogram); |
| 220 | 208 |
| 221 // Persistent histograms need some follow-up processing. | 209 // Persistent histograms need some follow-up processing. |
| 222 if (histogram_ref) { | 210 if (histogram_ref) { |
| 223 FinalizePersistentHistogram(histogram_ref, | 211 FinalizePersistentHistogram(histogram_ref, |
| 224 histogram == tentative_histogram); | 212 histogram == tentative_histogram); |
| 225 } | 213 } |
| 226 } | 214 } |
| 227 | 215 |
| 228 DCHECK_EQ(histogram_type_, histogram->GetHistogramType()); | 216 DCHECK_EQ(histogram_type_, histogram->GetHistogramType()); |
| 229 bool bad_args = false; | |
| 230 Sample existing_minimum = static_cast<Histogram*>(histogram)->declared_min_; | |
| 231 Sample existing_maximum = static_cast<Histogram*>(histogram)->declared_max_; | |
| 232 uint32_t existing_bucket_count = | |
| 233 static_cast<Histogram*>(histogram)->bucket_count(); | |
| 234 | |
| 235 if (bucket_count_ != 0 && | 217 if (bucket_count_ != 0 && |
| 236 !histogram->HasConstructionArguments(minimum_, maximum_, bucket_count_)) { | 218 !histogram->HasConstructionArguments(minimum_, maximum_, bucket_count_)) { |
| 237 // The construction arguments do not match the existing histogram. This can | 219 // The construction arguments do not match the existing histogram. This can |
| 238 // come about if an extension updates in the middle of a chrome run and has | 220 // come about if an extension updates in the middle of a chrome run and has |
| 239 // changed one of them, or simply by bad code within Chrome itself. We | 221 // changed one of them, or simply by bad code within Chrome itself. We |
| 240 // return NULL here with the expectation that bad code in Chrome will crash | 222 // return NULL here with the expectation that bad code in Chrome will crash |
| 241 // on dereference, but extension/Pepper APIs will guard against NULL and not | 223 // on dereference, but extension/Pepper APIs will guard against NULL and not |
| 242 // crash. | 224 // crash. |
| 243 DLOG(ERROR) << "Histogram " << name_ << " has bad construction arguments"; | 225 DLOG(ERROR) << "Histogram " << name_ << " has bad construction arguments"; |
| 244 bad_args = true; | 226 return nullptr; |
| 245 histogram = nullptr; | |
| 246 } | 227 } |
| 247 | |
| 248 #if !DCHECK_IS_ON() // Don't affect tests, only release builds. | |
| 249 // For the moment, crash here so that collected crash reports have access | |
| 250 // to the construction values in order to figure out why this is failing. | |
| 251 // TODO(bcwhite): Remove this once crbug.com/588946 is resolved. Also remove | |
| 252 // from beta-branch because we don't want crashes due to misbehaving | |
| 253 // extensions (see comment above). | |
| 254 if (!histogram) { | |
| 255 HistogramType histogram_type = histogram_type_; | |
| 256 HistogramBase::Sample minimum = minimum_; | |
| 257 HistogramBase::Sample maximum = maximum_; | |
| 258 uint32_t bucket_count = bucket_count_; | |
| 259 int32_t flags = flags_; | |
| 260 CHECK(histogram) << name_ << ": bad-args=" << bad_args; | |
| 261 base::debug::Alias(&histogram_type); | |
| 262 base::debug::Alias(&minimum); | |
| 263 base::debug::Alias(&maximum); | |
| 264 base::debug::Alias(&bucket_count); | |
| 265 base::debug::Alias(&flags); | |
| 266 base::debug::Alias(&created_ranges); | |
| 267 base::debug::Alias(®istered_ranges); | |
| 268 base::debug::Alias(&histogram_ref); | |
| 269 base::debug::Alias(&tentative_histogram); | |
| 270 base::debug::Alias(&allocator); | |
| 271 base::debug::Alias(&tentative_histogram); | |
| 272 } | |
| 273 #endif | |
| 274 | |
| 275 // Down here so vars are always "used". | |
| 276 base::debug::Alias(&bad_args); | |
| 277 base::debug::Alias(&existing_minimum); | |
| 278 base::debug::Alias(&existing_maximum); | |
| 279 base::debug::Alias(&existing_bucket_count); | |
| 280 return histogram; | 228 return histogram; |
| 281 } | 229 } |
| 282 | 230 |
| 283 HistogramBase* Histogram::FactoryGet(const std::string& name, | 231 HistogramBase* Histogram::FactoryGet(const std::string& name, |
| 284 Sample minimum, | 232 Sample minimum, |
| 285 Sample maximum, | 233 Sample maximum, |
| 286 uint32_t bucket_count, | 234 uint32_t bucket_count, |
| 287 int32_t flags) { | 235 int32_t flags) { |
| 288 bool valid_arguments = | 236 bool valid_arguments = |
| 289 InspectConstructionArguments(name, &minimum, &maximum, &bucket_count); | 237 InspectConstructionArguments(name, &minimum, &maximum, &bucket_count); |
| (...skipping 917 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1207 Sample sample = custom_ranges[i]; | 1155 Sample sample = custom_ranges[i]; |
| 1208 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) | 1156 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) |
| 1209 return false; | 1157 return false; |
| 1210 if (sample != 0) | 1158 if (sample != 0) |
| 1211 has_valid_range = true; | 1159 has_valid_range = true; |
| 1212 } | 1160 } |
| 1213 return has_valid_range; | 1161 return has_valid_range; |
| 1214 } | 1162 } |
| 1215 | 1163 |
| 1216 } // namespace base | 1164 } // namespace base |
| OLD | NEW |