pi_apm/
counter.rs

1//! # 用于性能采集的计数器
2//!
3
4use std::time;
5use std::thread;
6use std::sync::{Arc, Mutex};
7use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
8
9use lazy_static;
10use fnv::FnvHashMap;
11use parking_lot::RwLock;
12use crossbeam_queue::ArrayQueue;
13
14use atom::Atom;
15
16/*
17* 最小动态计数器容量
18*/
19const MIN_DYNAMIC_COUNTER_CAPACITY: usize = 10;
20
21/*
22* 默认动态计数器容量
23*/
24const DEFAULT_DYNAMIC_COUNTER_CAPACITY: usize = 1000000;
25
26/*
27* 最小静态计数器容量
28*/
29const MIN_STATIC_COUNTER_CAPACITY: usize = 1;
30
31/*
32* 默认静态计数器容量
33*/
34const DEFAULT_STATIC_COUNTER_CAPACITY: usize = 1000;
35
36///
37/// 全局并发性能采集
38///
39lazy_static! {
40    pub static ref GLOBAL_PREF_COLLECT: PrefCollect = PrefCollect::new(DEFAULT_DYNAMIC_COUNTER_CAPACITY, DEFAULT_STATIC_COUNTER_CAPACITY);
41}
42
43///
44/// 检查指定计数器名称与计数器id是否匹配
45///
46pub fn check_counter(name: &str, cid: u64) -> bool {
47    Atom::from(name).str_hash() as u64 == cid
48}
49
50///
51/// 并发性能计数器
52///
53#[derive(Debug, Clone)]
54pub struct PrefCounter(Arc<AtomicUsize>);
55
56unsafe impl Send for PrefCounter {}
57unsafe impl Sync for PrefCounter {}
58
59impl PrefCounter {
60    /// 获取
61    pub fn get(&self) -> usize {
62        self.0.load(Ordering::SeqCst)
63    }
64
65    /// 重置
66    pub fn set(&self, count: usize) {
67        self.0.store(count, Ordering::SeqCst);
68    }
69
70    /// 计数
71    pub fn sum(&self, count: usize) {
72        self.0.fetch_add(count, Ordering::Relaxed);
73    }
74}
75
76///
77/// 并发性能计时器
78///
79type StartTime = time::Instant;
80
81///
82/// 性能定时器
83///
84#[derive(Debug, Clone)]
85pub struct PrefTimer(Arc<AtomicUsize>);
86
87unsafe impl Send for PrefTimer {}
88unsafe impl Sync for PrefTimer {}
89
90impl PrefTimer {
91    /// 获取
92    pub fn get(&self) -> usize {
93        self.0.load(Ordering::Relaxed)
94    }
95
96    /// 开始计时
97    pub fn start(&self) -> StartTime {
98        StartTime::now()
99    }
100
101    /// 计时
102    pub fn timing(&self, start: StartTime) {
103        self.0.fetch_add((StartTime::now() - start).as_micros() as usize, Ordering::Relaxed);
104    }
105}
106
107///
108/// 动态计数器队列迭代器
109///
110pub struct DynamicIterator {
111    inner: Arc<InnerCollect>,
112    cache: Vec<(u64, Arc<AtomicUsize>)>,
113}
114
115impl Drop for DynamicIterator {
116    fn drop(&mut self) {
117        for _ in 0..self.cache.len() {
118            //返还缓存的动态计数器
119            self.inner.dynamic_collect.push(self.cache.remove(0));
120        }
121    }
122}
123
124impl Iterator for DynamicIterator {
125    type Item = (u64, Arc<AtomicUsize>);
126
127    fn next(&mut self) -> Option<Self::Item> {
128        if let Ok(counter) = self.inner.dynamic_collect.pop() {
129            if Arc::strong_count(&(counter.1)) == 2 {
130                //外部没有使用当前动态计数器,则从动态计数器表中移出指定动态计数器,并直接返回
131                self.inner.dynamic_table.write().remove(&(counter.0));
132                return Some(counter);
133            }
134
135            //外部还在使用当前动态计数器,则返回复制
136            let r = Some((counter.0, counter.1.clone()));
137            self.cache.push(counter);
138            return r;
139        }
140
141        None
142    }
143}
144
145///
146/// 静态计数器队列迭代器
147///
148pub struct StaticIterator {
149    inner: Arc<InnerCollect>,
150    cache: Vec<(u64, Arc<AtomicUsize>)>,
151}
152
153impl Drop for StaticIterator {
154    fn drop(&mut self) {
155        for _ in 0..self.cache.len() {
156            //返还缓存的静态计数器
157            self.inner.static_collect.push(self.cache.remove(0));
158        }
159    }
160}
161
162impl Iterator for StaticIterator {
163    type Item = (u64, Arc<AtomicUsize>);
164
165    fn next(&mut self) -> Option<Self::Item> {
166        if let Ok(counter) = self.inner.static_collect.pop() {
167            let r = Some((counter.0, counter.1.clone()));
168            self.cache.push(counter);
169            return r;
170        }
171
172        None
173    }
174}
175
176///
177/// 并发性能采集
178///
179#[derive(Clone)]
180pub struct PrefCollect(Arc<InnerCollect>);
181
182unsafe impl Send for PrefCollect {}
183unsafe impl Sync for PrefCollect {}
184
185struct InnerCollect {
186    dynamic_table:      RwLock<FnvHashMap<u64, Arc<AtomicUsize>>>,  //动态计数器表,用于随机查询指定的动态计数器
187    dynamic_collect:    ArrayQueue<(u64, Arc<AtomicUsize>)>,        //动态计数器队列,运行时可以动态增删计数器
188    static_init:        AtomicBool,                                 //静态计数器队列初始化标记
189    static_collect:     ArrayQueue<(u64, Arc<AtomicUsize>)>,        //静态计数器队列,初始化后无法增删计数器
190}
191
192impl PrefCollect {
193    /// 构建并发性能采集
194    pub fn new(dynamic_capacity: usize, static_capacity: usize) -> Self {
195        if dynamic_capacity < MIN_DYNAMIC_COUNTER_CAPACITY {
196            panic!("invalid dynamic capacity");
197        }
198        if static_capacity < MIN_STATIC_COUNTER_CAPACITY {
199            panic!("invalid static capacity");
200        }
201
202        PrefCollect(Arc::new(InnerCollect {
203            dynamic_table: RwLock::new(FnvHashMap::default()),
204            dynamic_collect: ArrayQueue::new(dynamic_capacity),
205            static_init: AtomicBool::new(false),
206            static_collect: ArrayQueue::new(static_capacity),
207        }))
208    }
209
210    /// 动态计数器队列是否已满
211    pub fn dynamic_is_full(&self) -> bool {
212        self.0.dynamic_collect.is_full()
213    }
214
215    /// 动态计数器数量
216    pub fn dynamic_size(&self) -> usize {
217        self.0.dynamic_collect.len()
218    }
219
220    /// 构建指定性能指标和初始值的动态计数器
221    pub fn new_dynamic_counter(&self, target: Atom, init: usize) -> Option<PrefCounter> {
222        if self.0.dynamic_collect.is_full() {
223            //动态计数器队列已满
224            return None;
225        }
226
227        let cid = target.str_hash();
228        if let Some(counter) = self.0.dynamic_table.read().get(&(cid as u64)) {
229            //存在指定的动态计数器
230            return Some(PrefCounter(counter.clone()));
231        }
232
233        //不存在指定的动态计数器
234        let counter = Arc::new(AtomicUsize::new(init));
235        self.0.dynamic_collect.push((cid as u64, counter.clone()));
236        self.0.dynamic_table.write().insert(cid as u64, counter.clone());
237        Some(PrefCounter(counter))
238    }
239
240    /// 构建指定性能指标和初始值的动态计时器
241    pub fn new_dynamic_timer(&self, target: Atom, init: usize) -> Option<PrefTimer> {
242        if self.0.dynamic_collect.is_full() {
243            //动态计数器队列已满
244            return None;
245        }
246
247        let cid = target.str_hash();
248        if let Some(counter) = self.0.dynamic_table.read().get(&(cid as u64)) {
249            //存在指定的动态计时器
250            return Some(PrefTimer(counter.clone()));
251        }
252
253        //不存在指定的动态计时器
254        let counter = Arc::new(AtomicUsize::new(init));
255        self.0.dynamic_collect.push((cid as u64, counter.clone()));
256        self.0.dynamic_table.write().insert(cid as u64, counter.clone());
257        Some(PrefTimer(counter))
258    }
259
260    /// 获取动态计数器的迭代器
261    pub fn dynamic_iter(&self) -> DynamicIterator {
262        DynamicIterator {
263            inner: self.0.clone(),
264            cache: Vec::with_capacity(self.0.dynamic_collect.len()),
265        }
266    }
267
268    /// 静态计数器队列是否已满
269    pub fn static_is_full(&self) -> bool {
270        self.0.static_collect.is_full()
271    }
272
273    /// 静态计数器数量
274    pub fn static_size(&self) -> usize {
275        self.0.static_collect.len()
276    }
277
278    /// 构建指定性能指标和初始值的静态计数器
279    pub fn new_static_counter(&self, target: Atom, init: usize) -> Option<PrefCounter> {
280        if self.0.static_init.load(Ordering::SeqCst) {
281            //初始化已完成,则忽略
282            return None;
283        }
284
285        let cid = target.str_hash();
286        let counter = Arc::new(AtomicUsize::new(init));
287        self.0.static_collect.push((cid as u64, counter.clone()));
288        Some(PrefCounter(counter))
289    }
290
291    /// 构建指定性能指标和初始值的静态计时器
292    pub fn new_static_timer(&self, target: Atom, init: usize) -> Option<PrefTimer> {
293        if self.0.static_init.load(Ordering::SeqCst) {
294            //初始化已完成,则忽略
295            return None;
296        }
297
298        let cid = target.str_hash();
299        let counter = Arc::new(AtomicUsize::new(init));
300        self.0.static_collect.push((cid as u64, counter.clone()));
301        Some(PrefTimer(counter))
302    }
303
304    /// 初始化静态计数器队列完成,返回静态计数器队列长度
305    pub fn static_init_ok(&self) -> usize {
306        self.0.static_init.compare_and_swap(false, true, Ordering::SeqCst);
307        self.0.static_collect.len()
308    }
309
310    /// 获取静态计数器的迭代器
311    pub fn static_iter(&self) -> StaticIterator {
312        StaticIterator {
313            inner: self.0.clone(),
314            cache: Vec::with_capacity(self.0.static_collect.len()),
315        }
316    }
317}