Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
|
Mark P
2016/09/23 19:30:42
Some of the macros in this file need better commen
rkaplow
2016/09/26 20:16:11
Acknowledged.
| |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef BASE_METRICS_HISTOGRAM_MACROS_INTERNAL_H_ | |
| 6 #define BASE_METRICS_HISTOGRAM_MACROS_INTERNAL_H_ | |
| 7 | |
| 8 #include "base/atomicops.h" | |
| 9 #include "base/logging.h" | |
| 10 #include "base/metrics/histogram.h" | |
| 11 #include "base/time/time.h" | |
| 12 | |
| 13 //------------------------------------------------------------------------------ | |
| 14 // Histograms are often put in areas where they are called many many times, and | |
| 15 // performance is critical. As a result, they are designed to have a very low | |
| 16 // recurring cost of executing (adding additional samples). Toward that end, | |
| 17 // the macros declare a static pointer to the histogram in question, and only | |
| 18 // take a "slow path" to construct (or find) the histogram on the first run | |
| 19 // through the macro. We leak the histograms at shutdown time so that we don't | |
| 20 // have to validate using the pointers at any time during the running of the | |
| 21 // process. | |
| 22 | |
| 23 | |
| 24 // In some cases (integration into 3rd party code), it's useful to separate the | |
| 25 // definition of |atomic_histogram_pointer| from its use. To achieve this we | |
| 26 // define HISTOGRAM_POINTER_USE, which uses an |atomic_histogram_pointer|, and | |
| 27 // STATIC_HISTOGRAM_POINTER_BLOCK, which defines an |atomic_histogram_pointer| | |
| 28 // and forwards to HISTOGRAM_POINTER_USE. | |
| 29 #define HISTOGRAM_POINTER_USE(atomic_histogram_pointer, \ | |
| 30 constant_histogram_name, \ | |
| 31 histogram_add_method_invocation, \ | |
| 32 histogram_factory_get_invocation) \ | |
| 33 do { \ | |
| 34 /* \ | |
| 35 * Acquire_Load() ensures that we acquire visibility to the \ | |
| 36 * pointed-to data in the histogram. \ | |
| 37 */ \ | |
| 38 base::HistogramBase* histogram_pointer( \ | |
| 39 reinterpret_cast<base::HistogramBase*>( \ | |
| 40 base::subtle::Acquire_Load(atomic_histogram_pointer))); \ | |
| 41 if (!histogram_pointer) { \ | |
| 42 /* \ | |
| 43 * This is the slow path, which will construct OR find the \ | |
| 44 * matching histogram. histogram_factory_get_invocation includes \ | |
| 45 * locks on a global histogram name map and is completely thread \ | |
| 46 * safe. \ | |
| 47 */ \ | |
| 48 histogram_pointer = histogram_factory_get_invocation; \ | |
| 49 \ | |
| 50 /* \ | |
| 51 * Use Release_Store to ensure that the histogram data is made \ | |
| 52 * available globally before we make the pointer visible. Several \ | |
| 53 * threads may perform this store, but the same value will be \ | |
| 54 * stored in all cases (for a given named/spec'ed histogram). \ | |
| 55 * We could do this without any barrier, since FactoryGet entered \ | |
| 56 * and exited a lock after construction, but this barrier makes \ | |
| 57 * things clear. \ | |
| 58 */ \ | |
| 59 base::subtle::Release_Store( \ | |
| 60 atomic_histogram_pointer, \ | |
| 61 reinterpret_cast<base::subtle::AtomicWord>(histogram_pointer)); \ | |
| 62 } \ | |
| 63 if (DCHECK_IS_ON()) \ | |
| 64 histogram_pointer->CheckName(constant_histogram_name); \ | |
| 65 histogram_pointer->histogram_add_method_invocation; \ | |
| 66 } while (0) | |
| 67 | |
| 68 // Defines the static |atomic_histogram_pointer| and forwards to | |
| 69 // HISTOGRAM_POINTER_USE. | |
| 70 #define STATIC_HISTOGRAM_POINTER_BLOCK(constant_histogram_name, \ | |
| 71 histogram_add_method_invocation, \ | |
| 72 histogram_factory_get_invocation) \ | |
| 73 do { \ | |
| 74 /* \ | |
| 75 * The pointer's presence indicates that the initialization is complete. \ | |
| 76 * Initialization is idempotent, so it can safely be atomically repeated. \ | |
| 77 */ \ | |
| 78 static base::subtle::AtomicWord atomic_histogram_pointer = 0; \ | |
| 79 HISTOGRAM_POINTER_USE(&atomic_histogram_pointer, constant_histogram_name, \ | |
| 80 histogram_add_method_invocation, \ | |
| 81 histogram_factory_get_invocation); \ | |
| 82 } while (0) | |
| 83 | |
| 84 // This is a helper macro used by other macros and shouldn't be used directly. | |
| 85 #define INTERNAL_HISTOGRAM_CUSTOM_COUNTS_WITH_FLAG(name, sample, min, max, \ | |
| 86 bucket_count, flag) \ | |
| 87 STATIC_HISTOGRAM_POINTER_BLOCK( \ | |
| 88 name, Add(sample), \ | |
| 89 base::Histogram::FactoryGet(name, min, max, bucket_count, flag)) | |
| 90 | |
| 91 // This is a helper macro used by other macros and shouldn't be used directly. | |
| 92 // One additional bucket is created in the LinearHistogram for the illegal | |
| 93 // values >= boundary_value so that mistakes in calling the UMA enumeration | |
| 94 // macros can be detected. | |
| 95 #define INTERNAL_HISTOGRAM_ENUMERATION_WITH_FLAG(name, sample, boundary, flag) \ | |
| 96 STATIC_HISTOGRAM_POINTER_BLOCK( \ | |
| 97 name, Add(sample), \ | |
| 98 base::LinearHistogram::FactoryGet( \ | |
| 99 name, 1, boundary, boundary + 1, flag)) | |
| 100 | |
| 101 | |
|
Mark P
2016/09/23 19:30:42
nit: extra blank line
rkaplow
2016/09/26 20:16:10
Done.
| |
| 102 // This nested macro is necessary to expand __COUNTER__ to an actual value. | |
|
Mark P
2016/09/23 19:30:42
warning comment about helper macro?
rkaplow
2016/09/26 20:16:10
Done.
| |
| 103 #define SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER(name, is_long, key) \ | |
| 104 SCOPED_UMA_HISTOGRAM_TIMER_UNIQUE(name, is_long, key) | |
| 105 | |
| 106 | |
|
Mark P
2016/09/23 19:30:42
nit: extra blank line
rkaplow
2016/09/26 20:16:11
Done.
| |
| 107 #define SCOPED_UMA_HISTOGRAM_TIMER_UNIQUE(name, is_long, key) \ | |
|
Mark P
2016/09/23 19:30:42
warning comment about helper macro?
rkaplow
2016/09/26 20:16:11
Done.
| |
| 108 class ScopedHistogramTimer##key { \ | |
| 109 public: \ | |
| 110 ScopedHistogramTimer##key() : constructed_(base::TimeTicks::Now()) {} \ | |
| 111 ~ScopedHistogramTimer##key() { \ | |
| 112 base::TimeDelta elapsed = base::TimeTicks::Now() - constructed_; \ | |
| 113 if (is_long) { \ | |
| 114 UMA_HISTOGRAM_LONG_TIMES_100(name, elapsed); \ | |
| 115 } else { \ | |
| 116 UMA_HISTOGRAM_TIMES(name, elapsed); \ | |
| 117 } \ | |
| 118 } \ | |
| 119 private: \ | |
| 120 base::TimeTicks constructed_; \ | |
| 121 } scoped_histogram_timer_##key | |
| 122 | |
| 123 #endif // BASE_METRICS_HISTOGRAM_MACROS_INTERNAL_H_ | |
| OLD | NEW |