| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 | 8 |
| 9 // It supports calls to accumulate either time intervals (which are processed | 9 // It supports calls to accumulate either time intervals (which are processed |
| 10 // as integral number of milliseconds), or arbitrary integral units. | 10 // as integral number of milliseconds), or arbitrary integral units. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 // pointer is NOT deleted, and we leak the histograms at process termination. | 38 // pointer is NOT deleted, and we leak the histograms at process termination. |
| 39 | 39 |
| 40 #ifndef BASE_METRICS_HISTOGRAM_H_ | 40 #ifndef BASE_METRICS_HISTOGRAM_H_ |
| 41 #define BASE_METRICS_HISTOGRAM_H_ | 41 #define BASE_METRICS_HISTOGRAM_H_ |
| 42 #pragma once | 42 #pragma once |
| 43 | 43 |
| 44 #include <map> | 44 #include <map> |
| 45 #include <string> | 45 #include <string> |
| 46 #include <vector> | 46 #include <vector> |
| 47 | 47 |
| 48 #include "base/atomicops.h" |
| 48 #include "base/base_export.h" | 49 #include "base/base_export.h" |
| 49 #include "base/gtest_prod_util.h" | 50 #include "base/gtest_prod_util.h" |
| 50 #include "base/logging.h" | 51 #include "base/logging.h" |
| 51 #include "base/time.h" | 52 #include "base/time.h" |
| 52 | 53 |
| 53 class Pickle; | 54 class Pickle; |
| 54 | 55 |
| 55 namespace base { | 56 namespace base { |
| 56 | 57 |
| 57 class Lock; | 58 class Lock; |
| 59 //------------------------------------------------------------------------------ |
| 60 // Histograms are often put in areas where they are called many many times, and |
| 61 // performance is critical. As a result, they are designed to have a very low |
| 62 // recurring cost of executing (adding additional samples). Toward that end, |
| 63 // the macros declare a static pointer to the histogram in question, and only |
| 64 // take a "slow path" to construct (or find) the histogram on the first run |
| 65 // through the macro. We leak the histograms at shutdown time so that we don't |
| 66 // have to validate using the pointers at any time during the running of the |
| 67 // process. |
| 68 |
| 69 // The following code is generally what a thread-safe static pointer |
| 70 // initializaion looks like for a histogram (after a macro is expanded). This |
| 71 // sample is an expansion (with comments) of the code for |
| 72 // HISTOGRAM_CUSTOM_COUNTS(). |
| 73 |
| 74 /* |
| 75 do { |
| 76 // The pointer's presence indicates the initialization is complete. |
| 77 // Initialization is idempotent, so it can safely be atomically repeated. |
| 78 static base::subtle::AtomicWord atomic_histogram_pointer = 0; |
| 79 |
| 80 // Acquire_Load() ensures that we acquire visibility to the pointed-to data |
| 81 // in the histogrom. |
| 82 base::Histogram* histogram_pointer(reinterpret_cast<base::Histogram*>( |
| 83 base::subtle::Acquire_Load(&atomic_histogram_pointer))); |
| 84 |
| 85 if (!histogram_pointer) { |
| 86 // This is the slow path, which will construct OR find the matching |
| 87 // histogram. FactoryGet includes locks on a global histogram name map |
| 88 // and is completely thread safe. |
| 89 histogram_pointer = base::Histogram::FactoryGet( |
| 90 name, min, max, bucket_count, base::Histogram::kNoFlags); |
| 91 |
| 92 // Use Release_Store to ensure that the histogram data is made available |
| 93 // globally before we make the pointer visible. |
| 94 // Several threads may perform this store, but the same value will be |
| 95 // stored in all cases (for a given named/spec'ed histogram). |
| 96 // We could do this without any barrier, since FactoryGet entered and |
| 97 // exited a lock after construction, but this barrier makes things clear. |
| 98 base::subtle::Release_Store(&atomic_histogram_pointer, |
| 99 reinterpret_cast<base::subtle::AtomicWord>(histogram_pointer)); |
| 100 } |
| 101 |
| 102 // Ensure calling contract is upheld, and the name does NOT vary. |
| 103 DCHECK(histogram_pointer->histogram_name() == constant_histogram_name); |
| 104 |
| 105 histogram_pointer->Add(sample); |
| 106 } while (0); |
| 107 */ |
| 108 |
| 109 // The above pattern is repeated in several macros. The only elements that |
| 110 // vary are the invocation of the Add(sample) vs AddTime(sample), and the choice |
| 111 // of which FactoryGet method to use. The different FactoryGet methods have |
| 112 // various argument lists, so the function with its argument list is provided as |
| 113 // a macro argument here. The name is only used in a DCHECK, to assure that |
| 114 // callers don't try to vary the name of the histogram (which would tend to be |
| 115 // ignored by the one-time initialization of the histogtram_pointer). |
| 116 #define STATIC_HISTOGRAM_POINTER_BLOCK(constant_histogram_name, \ |
| 117 histogram_add_method_invocation, \ |
| 118 histogram_factory_get_invocation) \ |
| 119 do { \ |
| 120 static base::subtle::AtomicWord atomic_histogram_pointer = 0; \ |
| 121 base::Histogram* histogram_pointer(reinterpret_cast<base::Histogram*>( \ |
| 122 base::subtle::Acquire_Load(&atomic_histogram_pointer))); \ |
| 123 if (!histogram_pointer) { \ |
| 124 histogram_pointer = histogram_factory_get_invocation; \ |
| 125 base::subtle::Release_Store(&atomic_histogram_pointer, \ |
| 126 reinterpret_cast<base::subtle::AtomicWord>(histogram_pointer)); \ |
| 127 } \ |
| 128 DCHECK(histogram_pointer->histogram_name() == constant_histogram_name); \ |
| 129 histogram_pointer->histogram_add_method_invocation; \ |
| 130 } while (0) |
| 131 |
| 58 | 132 |
| 59 //------------------------------------------------------------------------------ | 133 //------------------------------------------------------------------------------ |
| 60 // Provide easy general purpose histogram in a macro, just like stats counters. | 134 // Provide easy general purpose histogram in a macro, just like stats counters. |
| 61 // The first four macros use 50 buckets. | 135 // The first four macros use 50 buckets. |
| 62 | 136 |
| 63 #define HISTOGRAM_TIMES(name, sample) HISTOGRAM_CUSTOM_TIMES( \ | 137 #define HISTOGRAM_TIMES(name, sample) HISTOGRAM_CUSTOM_TIMES( \ |
| 64 name, sample, base::TimeDelta::FromMilliseconds(1), \ | 138 name, sample, base::TimeDelta::FromMilliseconds(1), \ |
| 65 base::TimeDelta::FromSeconds(10), 50) | 139 base::TimeDelta::FromSeconds(10), 50) |
| 66 | 140 |
| 67 #define HISTOGRAM_COUNTS(name, sample) HISTOGRAM_CUSTOM_COUNTS( \ | 141 #define HISTOGRAM_COUNTS(name, sample) HISTOGRAM_CUSTOM_COUNTS( \ |
| 68 name, sample, 1, 1000000, 50) | 142 name, sample, 1, 1000000, 50) |
| 69 | 143 |
| 70 #define HISTOGRAM_COUNTS_100(name, sample) HISTOGRAM_CUSTOM_COUNTS( \ | 144 #define HISTOGRAM_COUNTS_100(name, sample) HISTOGRAM_CUSTOM_COUNTS( \ |
| 71 name, sample, 1, 100, 50) | 145 name, sample, 1, 100, 50) |
| 72 | 146 |
| 73 #define HISTOGRAM_COUNTS_10000(name, sample) HISTOGRAM_CUSTOM_COUNTS( \ | 147 #define HISTOGRAM_COUNTS_10000(name, sample) HISTOGRAM_CUSTOM_COUNTS( \ |
| 74 name, sample, 1, 10000, 50) | 148 name, sample, 1, 10000, 50) |
| 75 | 149 |
| 76 #define HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \ | 150 #define HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \ |
| 77 static base::Histogram* counter(NULL); \ | 151 STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \ |
| 78 if (!counter) \ | 152 base::Histogram::FactoryGet(name, min, max, bucket_count, \ |
| 79 counter = base::Histogram::FactoryGet(name, min, max, bucket_count, \ | 153 base::Histogram::kNoFlags)) |
| 80 base::Histogram::kNoFlags); \ | |
| 81 DCHECK_EQ(name, counter->histogram_name()); \ | |
| 82 counter->Add(sample); \ | |
| 83 } while (0) | |
| 84 | 154 |
| 85 #define HISTOGRAM_PERCENTAGE(name, under_one_hundred) \ | 155 #define HISTOGRAM_PERCENTAGE(name, under_one_hundred) \ |
| 86 HISTOGRAM_ENUMERATION(name, under_one_hundred, 101) | 156 HISTOGRAM_ENUMERATION(name, under_one_hundred, 101) |
| 87 | 157 |
| 88 // For folks that need real specific times, use this to select a precise range | 158 // For folks that need real specific times, use this to select a precise range |
| 89 // of times you want plotted, and the number of buckets you want used. | 159 // of times you want plotted, and the number of buckets you want used. |
| 90 #define HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \ | 160 #define HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \ |
| 91 static base::Histogram* counter(NULL); \ | 161 STATIC_HISTOGRAM_POINTER_BLOCK(name, AddTime(sample), \ |
| 92 if (!counter) \ | 162 base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ |
| 93 counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ | 163 base::Histogram::kNoFlags)) |
| 94 base::Histogram::kNoFlags); \ | |
| 95 DCHECK_EQ(name, counter->histogram_name()); \ | |
| 96 counter->AddTime(sample); \ | |
| 97 } while (0) | |
| 98 | |
| 99 // DO NOT USE THIS. It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES. | |
| 100 #define HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \ | |
| 101 static base::Histogram* counter(NULL); \ | |
| 102 if (!counter) \ | |
| 103 counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ | |
| 104 base::Histogram::kNoFlags); \ | |
| 105 DCHECK_EQ(name, counter->histogram_name()); \ | |
| 106 if ((sample) < (max)) counter->AddTime(sample); \ | |
| 107 } while (0) | |
| 108 | 164 |
| 109 // Support histograming of an enumerated value. The samples should always be | 165 // Support histograming of an enumerated value. The samples should always be |
| 110 // less than boundary_value. | 166 // less than boundary_value. |
| 111 #define HISTOGRAM_ENUMERATION(name, sample, boundary_value) do { \ | 167 #define HISTOGRAM_ENUMERATION(name, sample, boundary_value) \ |
| 112 static base::Histogram* counter(NULL); \ | 168 STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \ |
| 113 if (!counter) \ | 169 base::LinearHistogram::FactoryGet(name, 1, boundary_value, \ |
| 114 counter = base::LinearHistogram::FactoryGet(name, 1, boundary_value, \ | 170 boundary_value + 1, base::Histogram::kNoFlags)) |
| 115 boundary_value + 1, base::Histogram::kNoFlags); \ | |
| 116 DCHECK_EQ(name, counter->histogram_name()); \ | |
| 117 counter->Add(sample); \ | |
| 118 } while (0) | |
| 119 | 171 |
| 120 // Support histograming of an enumerated value. Samples should be one of the | 172 // Support histograming of an enumerated value. Samples should be one of the |
| 121 // std::vector<int> list provided via |custom_ranges|. You can use the helper | 173 // std::vector<int> list provided via |custom_ranges|. You can use the helper |
| 122 // function |base::CustomHistogram::ArrayToCustomRanges(samples, num_samples)| | 174 // function |base::CustomHistogram::ArrayToCustomRanges(samples, num_samples)| |
| 123 // to transform a C-style array of valid sample values to a std::vector<int>. | 175 // to transform a C-style array of valid sample values to a std::vector<int>. |
| 124 #define HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) do { \ | 176 #define HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \ |
| 125 static base::Histogram* counter(NULL); \ | 177 STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \ |
| 126 if (!counter) \ | 178 base::CustomHistogram::FactoryGet(name, custom_ranges, \ |
| 127 counter = base::CustomHistogram::FactoryGet(name, custom_ranges, \ | 179 base::Histogram::kNoFlags)) |
| 128 base::Histogram::kNoFlags); \ | |
| 129 DCHECK_EQ(name, counter->histogram_name()); \ | |
| 130 counter->Add(sample); \ | |
| 131 } while (0) | |
| 132 | |
| 133 | 180 |
| 134 //------------------------------------------------------------------------------ | 181 //------------------------------------------------------------------------------ |
| 135 // Define Debug vs non-debug flavors of macros. | 182 // Define Debug vs non-debug flavors of macros. |
| 136 #ifndef NDEBUG | 183 #ifndef NDEBUG |
| 137 | 184 |
| 138 #define DHISTOGRAM_TIMES(name, sample) HISTOGRAM_TIMES(name, sample) | 185 #define DHISTOGRAM_TIMES(name, sample) HISTOGRAM_TIMES(name, sample) |
| 139 #define DHISTOGRAM_COUNTS(name, sample) HISTOGRAM_COUNTS(name, sample) | 186 #define DHISTOGRAM_COUNTS(name, sample) HISTOGRAM_COUNTS(name, sample) |
| 140 #define DHISTOGRAM_PERCENTAGE(name, under_one_hundred) HISTOGRAM_PERCENTAGE(\ | 187 #define DHISTOGRAM_PERCENTAGE(name, under_one_hundred) HISTOGRAM_PERCENTAGE(\ |
| 141 name, under_one_hundred) | 188 name, under_one_hundred) |
| 142 #define DHISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \ | 189 #define DHISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \ |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 | 226 |
| 180 #define UMA_HISTOGRAM_MEDIUM_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \ | 227 #define UMA_HISTOGRAM_MEDIUM_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \ |
| 181 name, sample, base::TimeDelta::FromMilliseconds(10), \ | 228 name, sample, base::TimeDelta::FromMilliseconds(10), \ |
| 182 base::TimeDelta::FromMinutes(3), 50) | 229 base::TimeDelta::FromMinutes(3), 50) |
| 183 | 230 |
| 184 // Use this macro when times can routinely be much longer than 10 seconds. | 231 // Use this macro when times can routinely be much longer than 10 seconds. |
| 185 #define UMA_HISTOGRAM_LONG_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \ | 232 #define UMA_HISTOGRAM_LONG_TIMES(name, sample) UMA_HISTOGRAM_CUSTOM_TIMES( \ |
| 186 name, sample, base::TimeDelta::FromMilliseconds(1), \ | 233 name, sample, base::TimeDelta::FromMilliseconds(1), \ |
| 187 base::TimeDelta::FromHours(1), 50) | 234 base::TimeDelta::FromHours(1), 50) |
| 188 | 235 |
| 189 #define UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) do { \ | 236 #define UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \ |
| 190 static base::Histogram* counter(NULL); \ | 237 STATIC_HISTOGRAM_POINTER_BLOCK(name, AddTime(sample), \ |
| 191 if (!counter) \ | 238 base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ |
| 192 counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ | 239 base::Histogram::kUmaTargetedHistogramFlag)) |
| 193 base::Histogram::kUmaTargetedHistogramFlag); \ | |
| 194 DCHECK_EQ(name, counter->histogram_name()); \ | |
| 195 counter->AddTime(sample); \ | |
| 196 } while (0) | |
| 197 | |
| 198 // DO NOT USE THIS. It is being phased out, in favor of HISTOGRAM_CUSTOM_TIMES. | |
| 199 #define UMA_HISTOGRAM_CLIPPED_TIMES(name, sample, min, max, bucket_count) do { \ | |
| 200 static base::Histogram* counter(NULL); \ | |
| 201 if (!counter) \ | |
| 202 counter = base::Histogram::FactoryTimeGet(name, min, max, bucket_count, \ | |
| 203 base::Histogram::kUmaTargetedHistogramFlag); \ | |
| 204 DCHECK_EQ(name, counter->histogram_name()); \ | |
| 205 if ((sample) < (max)) counter->AddTime(sample); \ | |
| 206 } while (0) | |
| 207 | 240 |
| 208 #define UMA_HISTOGRAM_COUNTS(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ | 241 #define UMA_HISTOGRAM_COUNTS(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
| 209 name, sample, 1, 1000000, 50) | 242 name, sample, 1, 1000000, 50) |
| 210 | 243 |
| 211 #define UMA_HISTOGRAM_COUNTS_100(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ | 244 #define UMA_HISTOGRAM_COUNTS_100(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
| 212 name, sample, 1, 100, 50) | 245 name, sample, 1, 100, 50) |
| 213 | 246 |
| 214 #define UMA_HISTOGRAM_COUNTS_10000(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ | 247 #define UMA_HISTOGRAM_COUNTS_10000(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
| 215 name, sample, 1, 10000, 50) | 248 name, sample, 1, 10000, 50) |
| 216 | 249 |
| 217 #define UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) do { \ | 250 #define UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \ |
| 218 static base::Histogram* counter(NULL); \ | 251 STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \ |
| 219 if (!counter) \ | 252 base::Histogram::FactoryGet(name, min, max, bucket_count, \ |
| 220 counter = base::Histogram::FactoryGet(name, min, max, bucket_count, \ | 253 base::Histogram::kUmaTargetedHistogramFlag)) |
| 221 base::Histogram::kUmaTargetedHistogramFlag); \ | |
| 222 DCHECK_EQ(name, counter->histogram_name()); \ | |
| 223 counter->Add(sample); \ | |
| 224 } while (0) | |
| 225 | 254 |
| 226 #define UMA_HISTOGRAM_MEMORY_KB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ | 255 #define UMA_HISTOGRAM_MEMORY_KB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
| 227 name, sample, 1000, 500000, 50) | 256 name, sample, 1000, 500000, 50) |
| 228 | 257 |
| 229 #define UMA_HISTOGRAM_MEMORY_MB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ | 258 #define UMA_HISTOGRAM_MEMORY_MB(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
| 230 name, sample, 1, 1000, 50) | 259 name, sample, 1, 1000, 50) |
| 231 | 260 |
| 232 #define UMA_HISTOGRAM_PERCENTAGE(name, under_one_hundred) \ | 261 #define UMA_HISTOGRAM_PERCENTAGE(name, under_one_hundred) \ |
| 233 UMA_HISTOGRAM_ENUMERATION(name, under_one_hundred, 101) | 262 UMA_HISTOGRAM_ENUMERATION(name, under_one_hundred, 101) |
| 234 | 263 |
| 235 #define UMA_HISTOGRAM_BOOLEAN(name, sample) do { \ | 264 #define UMA_HISTOGRAM_BOOLEAN(name, sample) \ |
| 236 static base::Histogram* counter(NULL); \ | 265 STATIC_HISTOGRAM_POINTER_BLOCK(name, AddBoolean(sample), \ |
| 237 if (!counter) \ | 266 base::BooleanHistogram::FactoryGet(name, \ |
| 238 counter = base::BooleanHistogram::FactoryGet(name, \ | 267 base::Histogram::kUmaTargetedHistogramFlag)) |
| 239 base::Histogram::kUmaTargetedHistogramFlag); \ | |
| 240 DCHECK_EQ(name, counter->histogram_name()); \ | |
| 241 counter->AddBoolean(sample); \ | |
| 242 } while (0) | |
| 243 | 268 |
| 244 #define UMA_HISTOGRAM_ENUMERATION(name, sample, boundary_value) do { \ | 269 #define UMA_HISTOGRAM_ENUMERATION(name, sample, boundary_value) \ |
| 245 static base::Histogram* counter(NULL); \ | 270 STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \ |
| 246 if (!counter) \ | 271 base::LinearHistogram::FactoryGet(name, 1, boundary_value, \ |
| 247 counter = base::LinearHistogram::FactoryGet(name, 1, boundary_value, \ | 272 boundary_value + 1, base::Histogram::kUmaTargetedHistogramFlag)) |
| 248 boundary_value + 1, base::Histogram::kUmaTargetedHistogramFlag); \ | |
| 249 DCHECK_EQ(name, counter->histogram_name()); \ | |
| 250 counter->Add(sample); \ | |
| 251 } while (0) | |
| 252 | 273 |
| 253 #define UMA_HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) do { \ | 274 #define UMA_HISTOGRAM_CUSTOM_ENUMERATION(name, sample, custom_ranges) \ |
| 254 static base::Histogram* counter(NULL); \ | 275 STATIC_HISTOGRAM_POINTER_BLOCK(name, Add(sample), \ |
| 255 if (!counter) \ | 276 base::CustomHistogram::FactoryGet(name, custom_ranges, \ |
| 256 counter = base::CustomHistogram::FactoryGet(name, custom_ranges, \ | 277 base::Histogram::kUmaTargetedHistogramFlag)) |
| 257 base::Histogram::kUmaTargetedHistogramFlag); \ | |
| 258 DCHECK_EQ(name, counter->histogram_name()); \ | |
| 259 counter->Add(sample); \ | |
| 260 } while (0) | |
| 261 | 278 |
| 262 //------------------------------------------------------------------------------ | 279 //------------------------------------------------------------------------------ |
| 263 | 280 |
| 264 class BooleanHistogram; | 281 class BooleanHistogram; |
| 265 class CustomHistogram; | 282 class CustomHistogram; |
| 266 class Histogram; | 283 class Histogram; |
| 267 class LinearHistogram; | 284 class LinearHistogram; |
| 268 | 285 |
| 269 class BASE_EXPORT Histogram { | 286 class BASE_EXPORT Histogram { |
| 270 public: | 287 public: |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 | 761 |
| 745 // Dump all known histograms to log. | 762 // Dump all known histograms to log. |
| 746 static bool dump_on_exit_; | 763 static bool dump_on_exit_; |
| 747 | 764 |
| 748 DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder); | 765 DISALLOW_COPY_AND_ASSIGN(StatisticsRecorder); |
| 749 }; | 766 }; |
| 750 | 767 |
| 751 } // namespace base | 768 } // namespace base |
| 752 | 769 |
| 753 #endif // BASE_METRICS_HISTOGRAM_H_ | 770 #endif // BASE_METRICS_HISTOGRAM_H_ |
| OLD | NEW |