Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / dmclock / support / src / profile.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 /*
5  * Copyright (C) 2016 Red Hat Inc.
6  */
7
8
9 #pragma once
10
11
12 #include <cmath>
13 #include <chrono>
14
15
16 namespace crimson {
17   template<typename T>
18   class ProfileBase {
19
20   protected:
21
22     using clock = std::chrono::steady_clock;
23
24     uint count = 0;
25     typename T::rep sum = 0;
26     typename T::rep sum_squares = 0;
27     typename T::rep low = 0;
28     typename T::rep high = 0;
29
30   public:
31
32     uint get_count() const { return count; }
33     typename T::rep get_sum() const { return sum; }
34     typename T::rep get_low() const { return low; }
35     typename T::rep get_high() const { return high; }
36     double get_mean() const {
37       if (0 == count) return nan("");
38       return sum / double(count); }
39     double get_std_dev() const {
40       if (0 == count) return nan("");
41       double variance =
42         (count * sum_squares - sum * sum) / double(count * count);
43       return sqrt(variance);
44     }
45   }; // class ProfileBase
46
47
48   // forward declaration for friend
49   template<typename T>
50   class ProfileCombiner;
51
52
53   template<typename T>
54   class ProfileTimer : public ProfileBase<T> {
55     friend ProfileCombiner<T>;
56
57     using super = ProfileBase<T>;
58
59     bool is_timing = false;
60     typename super::clock::time_point start_time;
61
62   public:
63
64     ProfileTimer() {
65     }
66
67     void start() {
68       assert(!is_timing);
69       start_time = super::clock::now();
70       is_timing = true;
71     }
72
73     void stop() {
74       assert(is_timing);
75       T duration = std::chrono::duration_cast<T>(super::clock::now() - start_time);
76       typename T::rep duration_count = duration.count();
77       this->sum += duration_count;
78       this->sum_squares += duration_count * duration_count;
79       if (0 == this->count) {
80         this->low = duration_count;
81         this->high = duration_count;
82       } else {
83         if (duration_count < this->low) this->low = duration_count;
84         else if (duration_count > this->high) this->high = duration_count;
85       }
86       ++this->count;
87       is_timing = false;
88     }
89   };  // class ProfileTimer
90
91
92   template<typename T>
93   class ProfileCombiner : public ProfileBase<T> {
94
95     using super = ProfileBase<T>;
96
97   public:
98
99     ProfileCombiner() {}
100
101     void combine(const ProfileTimer<T>& timer) {
102       if (0 == this->count) {
103         this->low = timer.low;
104         this->high = timer.high;
105       } else {
106         if (timer.low < this->low) this->low = timer.low;
107         else if (timer.high > this->high) this->high = timer.high;
108       }
109       this->count += timer.count;
110       this->sum += timer.sum;
111       this->sum_squares += timer.sum_squares;
112     }
113   }; // class ProfileCombiner
114 } // namespace crimson