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. | |
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 SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER(name, is_long, key) \ | |
Alexei Svitkine (slow)
2016/09/26 20:35:48
Nit: Add INTERNAL_ prefix here and to the macro be
rkaplow
2016/09/26 21:15:21
Done.
| |
107 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 SCOPED_UMA_HISTOGRAM_TIMER_UNIQUE(name, is_long, key) \ | |
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 |