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 |