/src/brpc/src/bvar/detail/sampler.h
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | // Date: Tue Jul 28 18:15:57 CST 2015 |
19 | | |
20 | | #ifndef BVAR_DETAIL_SAMPLER_H |
21 | | #define BVAR_DETAIL_SAMPLER_H |
22 | | |
23 | | #include <vector> |
24 | | #include <string> // std::string |
25 | | #include <type_traits> // std::true_type |
26 | | #include <utility> // std::declval |
27 | | #include "butil/containers/linked_list.h"// LinkNode |
28 | | #include "butil/scoped_lock.h" // BAIDU_SCOPED_LOCK |
29 | | #include "butil/logging.h" // LOG() |
30 | | #include "butil/containers/bounded_queue.h"// BoundedQueue |
31 | | #include "butil/type_traits.h" // is_same |
32 | | #include "butil/time.h" // cpuwide_time_us |
33 | | #include "butil/class_name.h" |
34 | | |
35 | | namespace bvar { |
36 | | namespace detail { |
37 | | |
38 | | template <typename T> |
39 | | struct Sample { |
40 | | T data; |
41 | | int64_t time_us; |
42 | | |
43 | 6 | Sample() : data(), time_us(0) {}Unexecuted instantiation: bvar::detail::Sample<bvar::detail::PercentileSamples<254ul> >::Sample() Unexecuted instantiation: bvar::detail::Sample<bvar::Stat>::Sample() bvar::detail::Sample<long>::Sample() Line | Count | Source | 43 | 4 | Sample() : data(), time_us(0) {} |
Unexecuted instantiation: bvar::detail::Sample<double>::Sample() Unexecuted instantiation: bvar::detail::Sample<unsigned long>::Sample() bvar::detail::Sample<int>::Sample() Line | Count | Source | 43 | 2 | Sample() : data(), time_us(0) {} |
|
44 | | Sample(const T& data2, int64_t time2) : data(data2), time_us(time2) {} |
45 | | }; |
46 | | |
47 | | // The base class for all samplers whose take_sample() are called periodically. |
48 | | class Sampler : public butil::LinkNode<Sampler> { |
49 | | public: |
50 | | Sampler(); |
51 | | |
52 | | // This function will be called every second(approximately) in a |
53 | | // dedicated thread if schedule() is called. |
54 | | virtual void take_sample() = 0; |
55 | | |
56 | | // Register this sampler globally so that take_sample() will be called |
57 | | // periodically. |
58 | | void schedule(); |
59 | | |
60 | | // Call this function instead of delete to destroy the sampler. Deletion |
61 | | // of the sampler may be delayed for seconds. |
62 | | void destroy(); |
63 | | |
64 | | // Declare/undeclare that an external object borrows this sampler which is |
65 | | // owned by another bvar. Window/PerSecond does this because it samples |
66 | | // through the sampler of the bvar it references. |
67 | | // If the owner is destructed while borrowers remain (namely a Window |
68 | | // outlives the bvar it references, which violates the contract documented |
69 | | // in bvar/window.h), destroy() reports the misuse and the sampler is |
70 | | // deliberately leaked so that borrowers are not left with a dangling |
71 | | // pointer. |
72 | | void add_borrower(); |
73 | | void remove_borrower(); |
74 | | |
75 | | // Name of the owning bvar, purely for diagnostics. |
76 | 3 | void set_debug_name(const std::string& name) { |
77 | 3 | BAIDU_SCOPED_LOCK(_mutex); |
78 | 3 | _debug_name = name; |
79 | 3 | } |
80 | 0 | std::string debug_name() const { |
81 | 0 | BAIDU_SCOPED_LOCK(_mutex); |
82 | 0 | return _debug_name; |
83 | 0 | } |
84 | | |
85 | | protected: |
86 | | virtual ~Sampler(); |
87 | | |
88 | | friend class SamplerCollector; |
89 | | bool _used; |
90 | | // Number of external borrowers, guarded by _mutex. |
91 | | int _nborrow; |
92 | | // Set by destroy() when _nborrow > 0, telling the sampling thread to leak |
93 | | // this sampler instead of deleting it. Guarded by _mutex. |
94 | | bool _leaked; |
95 | | mutable butil::Mutex _mutex; |
96 | | // For diagnostics only, see set_debug_name(). |
97 | | std::string _debug_name; |
98 | | }; |
99 | | |
100 | | // Representing a non-existing operator so that we can test |
101 | | // is_same<Op, VoidOp>::value to write code for different branches. |
102 | | // The false branch should be removed by compiler at compile-time. |
103 | | struct VoidOp { |
104 | | template <typename T> |
105 | 0 | T operator()(const T&, const T&) const { |
106 | 0 | CHECK(false) << "This function should never be called, abort"; |
107 | 0 | abort(); |
108 | 0 | } Unexecuted instantiation: long bvar::detail::VoidOp::operator()<long>(long const&, long const&) const Unexecuted instantiation: bvar::detail::PercentileSamples<254ul> bvar::detail::VoidOp::operator()<bvar::detail::PercentileSamples<254ul> >(bvar::detail::PercentileSamples<254ul> const&, bvar::detail::PercentileSamples<254ul> const&) const |
109 | | }; |
110 | | |
111 | | // Detects whether the host R exposes share_combiner(), namely whether its |
112 | | // sampling data lives in a shared_ptr-managed carrier (an AgentCombiner) that |
113 | | // the sampler is able to hold on its own. Hosts keeping the data elsewhere -- |
114 | | // a user callback in PassiveStatus, or a value-type babylon counter -- do NOT |
115 | | // provide it and are sampled through the host pointer as before. |
116 | | template <typename R> |
117 | | class HasShareCombiner { |
118 | | template <typename U> |
119 | | static auto probe(U* p) -> decltype(p->share_combiner(), std::true_type()); |
120 | | static std::false_type probe(...); |
121 | | public: |
122 | | static const bool value = decltype(probe(std::declval<R*>()))::value; |
123 | | }; |
124 | | |
125 | | // Samples through the host pointer, for hosts keeping their data outside a |
126 | | // shared carrier (a user callback in PassiveStatus, a value-type babylon |
127 | | // counter, ...). |
128 | | template <typename R, typename T, typename Op, typename InvOp> |
129 | | class HostSampleSource { |
130 | | public: |
131 | | explicit HostSampleSource(R* host) |
132 | 0 | : _host(host), _op(host->op()), _inv_op(host->inv_op()) {}Unexecuted instantiation: bvar::detail::HostSampleSource<bvar::PassiveStatus<double>, double, bvar::detail::AddTo<double>, bvar::detail::MinusFrom<double> >::HostSampleSource(bvar::PassiveStatus<double>*) Unexecuted instantiation: bvar::detail::HostSampleSource<bvar::PassiveStatus<long>, long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::HostSampleSource(bvar::PassiveStatus<long>*) Unexecuted instantiation: bvar::detail::HostSampleSource<bvar::PassiveStatus<unsigned long>, unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >::HostSampleSource(bvar::PassiveStatus<unsigned long>*) |
133 | | |
134 | | // Only reached from take_sample(), namely from the sampling thread, which is |
135 | | // mutually exclusive with the host's destroy(). The host is therefore always |
136 | | // alive here. |
137 | 0 | T reset() { return _host->reset(); }Unexecuted instantiation: bvar::detail::HostSampleSource<bvar::PassiveStatus<double>, double, bvar::detail::AddTo<double>, bvar::detail::MinusFrom<double> >::reset() Unexecuted instantiation: bvar::detail::HostSampleSource<bvar::PassiveStatus<long>, long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::reset() Unexecuted instantiation: bvar::detail::HostSampleSource<bvar::PassiveStatus<unsigned long>, unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >::reset() |
138 | 0 | T get_value() const { return _host->get_value(); }Unexecuted instantiation: bvar::detail::HostSampleSource<bvar::PassiveStatus<double>, double, bvar::detail::AddTo<double>, bvar::detail::MinusFrom<double> >::get_value() const Unexecuted instantiation: bvar::detail::HostSampleSource<bvar::PassiveStatus<long>, long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::get_value() const Unexecuted instantiation: bvar::detail::HostSampleSource<bvar::PassiveStatus<unsigned long>, unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >::get_value() const |
139 | | |
140 | | // Never touch the host, see the ctor. |
141 | 0 | const Op& op() const { return _op; }Unexecuted instantiation: bvar::detail::HostSampleSource<bvar::PassiveStatus<double>, double, bvar::detail::AddTo<double>, bvar::detail::MinusFrom<double> >::op() const Unexecuted instantiation: bvar::detail::HostSampleSource<bvar::PassiveStatus<long>, long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::op() const Unexecuted instantiation: bvar::detail::HostSampleSource<bvar::PassiveStatus<unsigned long>, unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >::op() const |
142 | 0 | const InvOp& inv_op() const { return _inv_op; }Unexecuted instantiation: bvar::detail::HostSampleSource<bvar::PassiveStatus<long>, long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::inv_op() const Unexecuted instantiation: bvar::detail::HostSampleSource<bvar::PassiveStatus<double>, double, bvar::detail::AddTo<double>, bvar::detail::MinusFrom<double> >::inv_op() const Unexecuted instantiation: bvar::detail::HostSampleSource<bvar::PassiveStatus<unsigned long>, unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >::inv_op() const |
143 | | |
144 | | private: |
145 | | R* _host; |
146 | | Op _op; |
147 | | InvOp _inv_op; |
148 | | }; |
149 | | |
150 | | // Samples directly from the shared data carrier, so that sampling still reads |
151 | | // valid memory even if the host is destructed before the sampler is recycled. |
152 | | // `Op'/`InvOp' are stateless functors, thus copied by value at construction and |
153 | | // the host is never touched afterwards. |
154 | | template <typename R, typename T, typename Op, typename InvOp> |
155 | | class CombinerSampleSource { |
156 | | public: |
157 | | explicit CombinerSampleSource(R* host) |
158 | 3 | : _combiner(host->share_combiner()) |
159 | 3 | , _op(host->op()) |
160 | 3 | , _inv_op(host->inv_op()) {}bvar::detail::CombinerSampleSource<bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >, long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::CombinerSampleSource(bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >*) Line | Count | Source | 158 | 2 | : _combiner(host->share_combiner()) | 159 | 2 | , _op(host->op()) | 160 | 2 | , _inv_op(host->inv_op()) {} |
bvar::detail::CombinerSampleSource<bvar::Reducer<int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >, int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >::CombinerSampleSource(bvar::Reducer<int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >*) Line | Count | Source | 158 | 1 | : _combiner(host->share_combiner()) | 159 | 1 | , _op(host->op()) | 160 | 1 | , _inv_op(host->inv_op()) {} |
Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::IntRecorder, bvar::Stat, bvar::detail::AddStat, bvar::detail::MinusStat>::CombinerSampleSource(bvar::IntRecorder*) Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>, long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>::CombinerSampleSource(bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>*) Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::detail::Percentile, bvar::detail::PercentileSamples<254ul>, bvar::detail::detail::AddPercentileSamples, bvar::detail::VoidOp>::CombinerSampleSource(bvar::detail::Percentile*) Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::Reducer<unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >, unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >::CombinerSampleSource(bvar::Reducer<unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >*) |
161 | | |
162 | 0 | T reset() { return _combiner->reset_all_agents(); }Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::IntRecorder, bvar::Stat, bvar::detail::AddStat, bvar::detail::MinusStat>::reset() Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::detail::Percentile, bvar::detail::PercentileSamples<254ul>, bvar::detail::detail::AddPercentileSamples, bvar::detail::VoidOp>::reset() Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::Reducer<int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >, int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >::reset() Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >, long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::reset() Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>, long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>::reset() Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::Reducer<unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >, unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >::reset() |
163 | 3 | T get_value() const { return _combiner->combine_agents(); }Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::IntRecorder, bvar::Stat, bvar::detail::AddStat, bvar::detail::MinusStat>::get_value() const Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::detail::Percentile, bvar::detail::PercentileSamples<254ul>, bvar::detail::detail::AddPercentileSamples, bvar::detail::VoidOp>::get_value() const bvar::detail::CombinerSampleSource<bvar::Reducer<int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >, int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >::get_value() const Line | Count | Source | 163 | 1 | T get_value() const { return _combiner->combine_agents(); } |
bvar::detail::CombinerSampleSource<bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >, long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::get_value() const Line | Count | Source | 163 | 2 | T get_value() const { return _combiner->combine_agents(); } |
Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>, long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>::get_value() const Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::Reducer<unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >, unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >::get_value() const |
164 | 0 | const Op& op() const { return _op; }Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::IntRecorder, bvar::Stat, bvar::detail::AddStat, bvar::detail::MinusStat>::op() const Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::Reducer<int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >, int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >::op() const Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >, long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::op() const Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>, long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>::op() const Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::detail::Percentile, bvar::detail::PercentileSamples<254ul>, bvar::detail::detail::AddPercentileSamples, bvar::detail::VoidOp>::op() const Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::Reducer<unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >, unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >::op() const |
165 | 0 | const InvOp& inv_op() const { return _inv_op; }Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::IntRecorder, bvar::Stat, bvar::detail::AddStat, bvar::detail::MinusStat>::inv_op() const Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::Reducer<int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >, int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >::inv_op() const Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >, long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::inv_op() const Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>, long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>::inv_op() const Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::detail::Percentile, bvar::detail::PercentileSamples<254ul>, bvar::detail::detail::AddPercentileSamples, bvar::detail::VoidOp>::inv_op() const Unexecuted instantiation: bvar::detail::CombinerSampleSource<bvar::Reducer<unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >, unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >::inv_op() const |
166 | | |
167 | | private: |
168 | | typename R::shared_combiner_type _combiner; |
169 | | Op _op; |
170 | | InvOp _inv_op; |
171 | | }; |
172 | | |
173 | | // The sampler for reducer-alike variables. |
174 | | // The R should have following methods: |
175 | | // - T reset(); |
176 | | // - T get_value(); |
177 | | // - Op op(); |
178 | | // - InvOp inv_op(); |
179 | | // Additionally, if R exposes |
180 | | // - shared_combiner_type share_combiner(); |
181 | | // the sampler holds that shared carrier instead of R itself, which makes |
182 | | // sampling immune to R being destructed first. |
183 | | template <typename R, typename T, typename Op, typename InvOp> |
184 | | class ReducerSampler : public Sampler { |
185 | | typedef typename butil::conditional< |
186 | | HasShareCombiner<R>::value, |
187 | | CombinerSampleSource<R, T, Op, InvOp>, |
188 | | HostSampleSource<R, T, Op, InvOp> >::type source_type; |
189 | | |
190 | | public: |
191 | | static const time_t MAX_SECONDS_LIMIT = 3600; |
192 | | |
193 | | explicit ReducerSampler(R* reducer) |
194 | 3 | : _source(reducer) |
195 | 3 | , _window_size(1) { |
196 | | |
197 | | // Invoked take_sample at begining so the value of the first second |
198 | | // would not be ignored |
199 | 3 | take_sample(); |
200 | 3 | } Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::PassiveStatus<double>, double, bvar::detail::AddTo<double>, bvar::detail::MinusFrom<double> >::ReducerSampler(bvar::PassiveStatus<double>*) Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::PassiveStatus<long>, long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::ReducerSampler(bvar::PassiveStatus<long>*) Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::PassiveStatus<unsigned long>, unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >::ReducerSampler(bvar::PassiveStatus<unsigned long>*) bvar::detail::ReducerSampler<bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >, long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::ReducerSampler(bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >*) Line | Count | Source | 194 | 2 | : _source(reducer) | 195 | 2 | , _window_size(1) { | 196 | | | 197 | | // Invoked take_sample at begining so the value of the first second | 198 | | // would not be ignored | 199 | 2 | take_sample(); | 200 | 2 | } |
bvar::detail::ReducerSampler<bvar::Reducer<int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >, int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >::ReducerSampler(bvar::Reducer<int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >*) Line | Count | Source | 194 | 1 | : _source(reducer) | 195 | 1 | , _window_size(1) { | 196 | | | 197 | | // Invoked take_sample at begining so the value of the first second | 198 | | // would not be ignored | 199 | 1 | take_sample(); | 200 | 1 | } |
Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::IntRecorder, bvar::Stat, bvar::detail::AddStat, bvar::detail::MinusStat>::ReducerSampler(bvar::IntRecorder*) Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>, long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>::ReducerSampler(bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>*) Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::detail::Percentile, bvar::detail::PercentileSamples<254ul>, bvar::detail::detail::AddPercentileSamples, bvar::detail::VoidOp>::ReducerSampler(bvar::detail::Percentile*) Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::Reducer<unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >, unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >::ReducerSampler(bvar::Reducer<unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >*) |
201 | 0 | ~ReducerSampler() {}Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::PassiveStatus<double>, double, bvar::detail::AddTo<double>, bvar::detail::MinusFrom<double> >::~ReducerSampler() Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::PassiveStatus<long>, long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::~ReducerSampler() Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::PassiveStatus<unsigned long>, unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >::~ReducerSampler() Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >, long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::~ReducerSampler() Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::Reducer<int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >, int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >::~ReducerSampler() Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::IntRecorder, bvar::Stat, bvar::detail::AddStat, bvar::detail::MinusStat>::~ReducerSampler() Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>, long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>::~ReducerSampler() Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::detail::Percentile, bvar::detail::PercentileSamples<254ul>, bvar::detail::detail::AddPercentileSamples, bvar::detail::VoidOp>::~ReducerSampler() Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::Reducer<unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >, unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >::~ReducerSampler() |
202 | | |
203 | 3 | void take_sample() override { |
204 | | // Make _q ready. |
205 | | // If _window_size is larger than what _q can hold, e.g. a larger |
206 | | // Window<> is created after running of sampler, make _q larger. |
207 | 3 | if ((size_t)_window_size + 1 > _q.capacity()) { |
208 | 3 | const size_t new_cap = |
209 | 3 | std::max(_q.capacity() * 2, (size_t)_window_size + 1); |
210 | 3 | const size_t memsize = sizeof(Sample<T>) * new_cap; |
211 | 3 | void* mem = malloc(memsize); |
212 | 3 | if (nullptr == mem) { |
213 | 0 | return; |
214 | 0 | } |
215 | 3 | butil::BoundedQueue<Sample<T> > new_q( |
216 | 3 | mem, memsize, butil::OWNS_STORAGE); |
217 | 3 | Sample<T> tmp; |
218 | 3 | while (_q.pop(&tmp)) { |
219 | 0 | new_q.push(tmp); |
220 | 0 | } |
221 | 3 | new_q.swap(_q); |
222 | 3 | } |
223 | | |
224 | 3 | Sample<T> latest; |
225 | 3 | if (butil::is_same<InvOp, VoidOp>::value) { |
226 | | // The operator can't be inversed. |
227 | | // We reset the reducer and save the result as a sample. |
228 | | // Suming up samples gives the result within a window. |
229 | | // In this case, get_value() of _reducer gives wrong answer and |
230 | | // should not be called. |
231 | 0 | latest.data = _source.reset(); |
232 | 3 | } else { |
233 | | // The operator can be inversed. |
234 | | // We save the result as a sample. |
235 | | // Inversed operation between latest and oldest sample within a |
236 | | // window gives result. |
237 | | // get_value() of _reducer can still be called. |
238 | 3 | latest.data = _source.get_value(); |
239 | 3 | } |
240 | 3 | latest.time_us = butil::cpuwide_time_us(); |
241 | 3 | _q.elim_push(latest); |
242 | 3 | } Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::IntRecorder, bvar::Stat, bvar::detail::AddStat, bvar::detail::MinusStat>::take_sample() Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::detail::Percentile, bvar::detail::PercentileSamples<254ul>, bvar::detail::detail::AddPercentileSamples, bvar::detail::VoidOp>::take_sample() bvar::detail::ReducerSampler<bvar::Reducer<int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >, int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >::take_sample() Line | Count | Source | 203 | 1 | void take_sample() override { | 204 | | // Make _q ready. | 205 | | // If _window_size is larger than what _q can hold, e.g. a larger | 206 | | // Window<> is created after running of sampler, make _q larger. | 207 | 1 | if ((size_t)_window_size + 1 > _q.capacity()) { | 208 | 1 | const size_t new_cap = | 209 | 1 | std::max(_q.capacity() * 2, (size_t)_window_size + 1); | 210 | 1 | const size_t memsize = sizeof(Sample<T>) * new_cap; | 211 | 1 | void* mem = malloc(memsize); | 212 | 1 | if (nullptr == mem) { | 213 | 0 | return; | 214 | 0 | } | 215 | 1 | butil::BoundedQueue<Sample<T> > new_q( | 216 | 1 | mem, memsize, butil::OWNS_STORAGE); | 217 | 1 | Sample<T> tmp; | 218 | 1 | while (_q.pop(&tmp)) { | 219 | 0 | new_q.push(tmp); | 220 | 0 | } | 221 | 1 | new_q.swap(_q); | 222 | 1 | } | 223 | | | 224 | 1 | Sample<T> latest; | 225 | 1 | if (butil::is_same<InvOp, VoidOp>::value) { | 226 | | // The operator can't be inversed. | 227 | | // We reset the reducer and save the result as a sample. | 228 | | // Suming up samples gives the result within a window. | 229 | | // In this case, get_value() of _reducer gives wrong answer and | 230 | | // should not be called. | 231 | 0 | latest.data = _source.reset(); | 232 | 1 | } else { | 233 | | // The operator can be inversed. | 234 | | // We save the result as a sample. | 235 | | // Inversed operation between latest and oldest sample within a | 236 | | // window gives result. | 237 | | // get_value() of _reducer can still be called. | 238 | 1 | latest.data = _source.get_value(); | 239 | 1 | } | 240 | 1 | latest.time_us = butil::cpuwide_time_us(); | 241 | 1 | _q.elim_push(latest); | 242 | 1 | } |
bvar::detail::ReducerSampler<bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >, long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::take_sample() Line | Count | Source | 203 | 2 | void take_sample() override { | 204 | | // Make _q ready. | 205 | | // If _window_size is larger than what _q can hold, e.g. a larger | 206 | | // Window<> is created after running of sampler, make _q larger. | 207 | 2 | if ((size_t)_window_size + 1 > _q.capacity()) { | 208 | 2 | const size_t new_cap = | 209 | 2 | std::max(_q.capacity() * 2, (size_t)_window_size + 1); | 210 | 2 | const size_t memsize = sizeof(Sample<T>) * new_cap; | 211 | 2 | void* mem = malloc(memsize); | 212 | 2 | if (nullptr == mem) { | 213 | 0 | return; | 214 | 0 | } | 215 | 2 | butil::BoundedQueue<Sample<T> > new_q( | 216 | 2 | mem, memsize, butil::OWNS_STORAGE); | 217 | 2 | Sample<T> tmp; | 218 | 2 | while (_q.pop(&tmp)) { | 219 | 0 | new_q.push(tmp); | 220 | 0 | } | 221 | 2 | new_q.swap(_q); | 222 | 2 | } | 223 | | | 224 | 2 | Sample<T> latest; | 225 | 2 | if (butil::is_same<InvOp, VoidOp>::value) { | 226 | | // The operator can't be inversed. | 227 | | // We reset the reducer and save the result as a sample. | 228 | | // Suming up samples gives the result within a window. | 229 | | // In this case, get_value() of _reducer gives wrong answer and | 230 | | // should not be called. | 231 | 0 | latest.data = _source.reset(); | 232 | 2 | } else { | 233 | | // The operator can be inversed. | 234 | | // We save the result as a sample. | 235 | | // Inversed operation between latest and oldest sample within a | 236 | | // window gives result. | 237 | | // get_value() of _reducer can still be called. | 238 | 2 | latest.data = _source.get_value(); | 239 | 2 | } | 240 | 2 | latest.time_us = butil::cpuwide_time_us(); | 241 | 2 | _q.elim_push(latest); | 242 | 2 | } |
Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::PassiveStatus<double>, double, bvar::detail::AddTo<double>, bvar::detail::MinusFrom<double> >::take_sample() Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::PassiveStatus<long>, long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::take_sample() Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::PassiveStatus<unsigned long>, unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >::take_sample() Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>, long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>::take_sample() Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::Reducer<unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >, unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >::take_sample() |
243 | | |
244 | 0 | bool get_value(time_t window_size, Sample<T>* result) { |
245 | 0 | if (window_size <= 0) { |
246 | 0 | LOG(FATAL) << "Invalid window_size=" << window_size; |
247 | 0 | return false; |
248 | 0 | } |
249 | 0 | BAIDU_SCOPED_LOCK(_mutex); |
250 | 0 | if (_q.size() <= 1UL) { |
251 | | // We need more samples to get reasonable result. |
252 | 0 | return false; |
253 | 0 | } |
254 | 0 | Sample<T>* oldest = _q.bottom(window_size); |
255 | 0 | if (nullptr == oldest) { |
256 | 0 | oldest = _q.top(); |
257 | 0 | } |
258 | 0 | Sample<T>* latest = _q.bottom(); |
259 | 0 | DCHECK(latest != oldest); |
260 | 0 | if (butil::is_same<InvOp, VoidOp>::value) { |
261 | | // No inverse op. Sum up all samples within the window. |
262 | 0 | result->data = latest->data; |
263 | 0 | for (int i = 1; true; ++i) { |
264 | 0 | Sample<T>* e = _q.bottom(i); |
265 | 0 | if (e == oldest) { |
266 | 0 | break; |
267 | 0 | } |
268 | 0 | _source.op()(result->data, e->data); |
269 | 0 | } |
270 | 0 | } else { |
271 | | // Diff the latest and oldest sample within the window. |
272 | 0 | result->data = latest->data; |
273 | 0 | _source.inv_op()(result->data, oldest->data); |
274 | 0 | } |
275 | 0 | result->time_us = latest->time_us - oldest->time_us; |
276 | 0 | return true; |
277 | 0 | } Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::IntRecorder, bvar::Stat, bvar::detail::AddStat, bvar::detail::MinusStat>::get_value(long, bvar::detail::Sample<bvar::Stat>*) Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::Reducer<int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >, int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >::get_value(long, bvar::detail::Sample<int>*) Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >, long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::get_value(long, bvar::detail::Sample<long>*) Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>, long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>::get_value(long, bvar::detail::Sample<long>*) Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::detail::Percentile, bvar::detail::PercentileSamples<254ul>, bvar::detail::detail::AddPercentileSamples, bvar::detail::VoidOp>::get_value(long, bvar::detail::Sample<bvar::detail::PercentileSamples<254ul> >*) Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::PassiveStatus<long>, long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::get_value(long, bvar::detail::Sample<long>*) Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::PassiveStatus<double>, double, bvar::detail::AddTo<double>, bvar::detail::MinusFrom<double> >::get_value(long, bvar::detail::Sample<double>*) Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::PassiveStatus<unsigned long>, unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >::get_value(long, bvar::detail::Sample<unsigned long>*) Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::Reducer<unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >, unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >::get_value(long, bvar::detail::Sample<unsigned long>*) |
278 | | |
279 | | // Change the time window which can only go larger. |
280 | 3 | int set_window_size(time_t window_size) { |
281 | 3 | if (window_size <= 0 || window_size > MAX_SECONDS_LIMIT) { |
282 | 0 | LOG(ERROR) << "Invalid window_size=" << window_size; |
283 | 0 | return -1; |
284 | 0 | } |
285 | 3 | BAIDU_SCOPED_LOCK(_mutex); |
286 | 3 | if (window_size > _window_size) { |
287 | 3 | _window_size = window_size; |
288 | 3 | } |
289 | 3 | return 0; |
290 | 3 | } bvar::detail::ReducerSampler<bvar::Reducer<int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >, int, bvar::detail::AddTo<int>, bvar::detail::MinusFrom<int> >::set_window_size(long) Line | Count | Source | 280 | 1 | int set_window_size(time_t window_size) { | 281 | 1 | if (window_size <= 0 || window_size > MAX_SECONDS_LIMIT) { | 282 | 0 | LOG(ERROR) << "Invalid window_size=" << window_size; | 283 | 0 | return -1; | 284 | 0 | } | 285 | 1 | BAIDU_SCOPED_LOCK(_mutex); | 286 | 1 | if (window_size > _window_size) { | 287 | 1 | _window_size = window_size; | 288 | 1 | } | 289 | 1 | return 0; | 290 | 1 | } |
bvar::detail::ReducerSampler<bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >, long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::set_window_size(long) Line | Count | Source | 280 | 2 | int set_window_size(time_t window_size) { | 281 | 2 | if (window_size <= 0 || window_size > MAX_SECONDS_LIMIT) { | 282 | 0 | LOG(ERROR) << "Invalid window_size=" << window_size; | 283 | 0 | return -1; | 284 | 0 | } | 285 | 2 | BAIDU_SCOPED_LOCK(_mutex); | 286 | 2 | if (window_size > _window_size) { | 287 | 2 | _window_size = window_size; | 288 | 2 | } | 289 | 2 | return 0; | 290 | 2 | } |
Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::PassiveStatus<double>, double, bvar::detail::AddTo<double>, bvar::detail::MinusFrom<double> >::set_window_size(long) Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::PassiveStatus<long>, long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::set_window_size(long) Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::PassiveStatus<unsigned long>, unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >::set_window_size(long) Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::IntRecorder, bvar::Stat, bvar::detail::AddStat, bvar::detail::MinusStat>::set_window_size(long) Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>, long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>::set_window_size(long) Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::detail::Percentile, bvar::detail::PercentileSamples<254ul>, bvar::detail::detail::AddPercentileSamples, bvar::detail::VoidOp>::set_window_size(long) Unexecuted instantiation: bvar::detail::ReducerSampler<bvar::Reducer<unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >, unsigned long, bvar::detail::AddTo<unsigned long>, bvar::detail::MinusFrom<unsigned long> >::set_window_size(long) |
291 | | |
292 | 0 | void get_samples(std::vector<T> *samples, time_t window_size) { |
293 | 0 | if (window_size <= 0) { |
294 | 0 | LOG(FATAL) << "Invalid window_size=" << window_size; |
295 | 0 | return; |
296 | 0 | } |
297 | 0 | BAIDU_SCOPED_LOCK(_mutex); |
298 | 0 | if (_q.size() <= 1) { |
299 | | // We need more samples to get reasonable result. |
300 | 0 | return; |
301 | 0 | } |
302 | 0 | Sample<T>* oldest = _q.bottom(window_size); |
303 | 0 | if (nullptr == oldest) { |
304 | 0 | oldest = _q.top(); |
305 | 0 | } |
306 | 0 | for (int i = 1; true; ++i) { |
307 | 0 | Sample<T>* e = _q.bottom(i); |
308 | 0 | if (e == oldest) { |
309 | 0 | break; |
310 | 0 | } |
311 | 0 | samples->push_back(e->data); |
312 | 0 | } |
313 | 0 | } |
314 | | |
315 | | private: |
316 | | source_type _source; |
317 | | time_t _window_size; |
318 | | butil::BoundedQueue<Sample<T> > _q; |
319 | | }; |
320 | | |
321 | | } // namespace detail |
322 | | } // namespace bvar |
323 | | |
324 | | #endif // BVAR_DETAIL_SAMPLER_H |