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