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