Spicy
timing.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
5 #pragma once
6 
7 #include <cassert>
8 #include <chrono>
9 #include <list>
10 #include <memory>
11 #include <string>
12 #include <unordered_map>
13 #include <utility>
14 
15 namespace hilti::util {
16 
17 namespace timing {
18 
19 using Clock = std::chrono::high_resolution_clock;
20 using Time = Clock::time_point;
21 using Duration = Clock::duration;
22 
23 class Collector;
24 class Ledger;
25 
26 namespace detail {
27 
29 class Manager {
30 public:
35  static void summary(std::ostream& out);
36 
42  static std::shared_ptr<Manager> singleton();
43 
44 protected:
45  friend Collector;
46  friend Ledger;
47 
48  Manager() : _created(Clock::now()) {}
49 
50  void register_(Ledger* ledger);
51  void unregister(Ledger* ledger);
52  Ledger* newLedger(const std::string& name);
53 
54 private:
55  Time _created;
56  std::unordered_map<std::string, Ledger*> _all_ledgers;
57  std::list<Ledger> _our_ledgers;
58 };
59 
60 } // namespace detail
61 
62 inline void summary(std::ostream& out) { detail::Manager::summary(out); }
63 
65 class Ledger {
66 public:
67  Ledger(std::string name) : _name(std::move(name)), _manager(detail::Manager::singleton()) {
68  _manager->register_(this);
69  }
70  ~Ledger() { _manager->unregister(this); }
71 
72  Ledger() = delete;
73  Ledger(const Ledger&) = default;
74  Ledger(Ledger&&) noexcept = default;
75  Ledger& operator=(const Ledger&) = delete;
76  Ledger& operator=(Ledger&&) noexcept = delete;
77 
78  const std::string& name() const { return _name; }
79 
80  void summary(std::ostream& out) const;
81 
82 protected:
83  friend class Collector;
84  friend class detail::Manager;
85 
86  void start() {
87  if ( _level < 0 )
88  return;
89 
90  if ( ++_level != 1 )
91  return;
92 
93  assert(_time_started == Time());
94  _time_started = Clock::now();
95  }
96 
97  void stop() {
98  if ( _level < 0 )
99  return;
100 
101  assert(_level > 0);
102 
103  if ( --_level != 0 )
104  return;
105 
106  assert(_time_started != Time());
107  _time_used += (Clock::now() - _time_started);
108  _time_started = Time();
109  ++_num_completed;
110  }
111 
112  void finish() {
113  if ( _level > 0 ) {
114  _time_used += (Clock::now() - _time_started);
115  _time_started = Time();
116  ++_num_completed;
117  }
118 
119  _level = -1;
120  }
121 
122  Duration _time_used = Duration(0);
123  uint64_t _num_completed = 0;
124  int64_t _level = 0;
125  std::string _name;
126 
127 private:
128  std::shared_ptr<detail::Manager> _manager;
129  Time _time_started;
130 };
131 
133 class Collector {
134 public:
135  Collector(Ledger* ledger) : _ledger(ledger) { ledger->start(); }
136 
137  Collector(const std::string& name) {
138  _ledger = detail::Manager::singleton()->newLedger(name);
139  _ledger->start();
140  }
141 
142  ~Collector() { _ledger->stop(); }
143 
144  void finish() { _ledger->finish(); }
145 
146  Collector() = delete;
147  Collector(const Collector&) = delete;
148  Collector(Collector&&) noexcept = delete;
149  Collector& operator=(const Collector&) = delete;
150  Collector& operator=(Collector&&) noexcept = delete;
151 
152 protected:
153  Ledger* _ledger;
154 };
155 
156 } // namespace timing
157 
158 } // namespace hilti::util
Definition: timing.h:133
Definition: cache.h:11
static void summary(std::ostream &out)
Definition: timing.cc:68
static std::shared_ptr< Manager > singleton()
Definition: timing.cc:41
Definition: timing.h:65