GComm  0.2.3
profile.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009 Codership Oy <info@codership.com>
3  */
4 
44 #ifndef GCOMM_PROFILE_HPP
45 #define GCOMM_PROFILE_HPP
46 
47 extern "C"
48 {
49 #include "gu_time.h"
50 }
51 
52 #include <map>
53 #include <ostream>
54 
55 namespace prof
56 {
57 
58  // Forward declarations
59  class Key;
60  class Point;
61  class Profile;
62  std::ostream& operator<<(std::ostream&, const Key&);
63  std::ostream& operator<<(std::ostream&, const Profile&);
64 }
65 
71 class prof::Key
72 {
73 public:
74  Key(const char* const file,
75  const char* const func,
76  const int line)
77  :
78  file_(file),
79  func_(func),
80  line_(line)
81  { }
82 
83  bool operator==(const Key& cmp) const
84  {
85  return (line_ == cmp.line_ &&
86  func_ == cmp.func_ &&
87  file_ == cmp.file_);
88  }
89 
90  bool operator<(const Key& cmp) const
91  {
92  return (line_ < cmp.line_ ||
93  (line_ == cmp.line_ && (func_ < cmp.func_ ||
94  (func_ == cmp.func_ && file_ < cmp.file_))));
95  }
96  std::string to_string() const
97  {
98  std::ostringstream os;
99  os << *this;
100  return os.str();
101  }
102 private:
103  friend class Point;
104  friend class Profile;
105  friend std::ostream& operator<<(std::ostream& os, const Key&);
106  const char* const file_;
107  const char* const func_;
108  const int line_;
109 };
110 
111 inline std::ostream& prof::operator<<(std::ostream& os, const prof::Key& key)
112 {
113  return os << key.file_ << ":" << key.func_ << ":" << key.line_;
114 }
115 
116 
118 {
119 public:
120  Point(const Profile& prof,
121  const char* file,
122  const char* func,
123  const int line);
124  ~Point();
125 private:
126  friend class Profile;
127  const Profile& prof_;
128  const Key key_;
129  mutable long long int enter_time_calendar_;
130  mutable long long int enter_time_thread_cputime_;
131 };
132 
137 {
138  struct PointStats
139  {
140  PointStats(long long int count = 0,
141  long long int time_calendar = 0,
142  long long int time_thread_cputime = 0) :
143  count_ (count ),
144  time_calendar_ (time_calendar ),
145  time_thread_cputime_(time_thread_cputime)
146  { }
147 
148  PointStats operator+(const PointStats& add) const
149  {
150  return PointStats(count_ + add.count_,
151  time_calendar_ + add.time_calendar_,
152  time_thread_cputime_ + add.time_thread_cputime_);
153  }
154 
155  long long int count_;
156  long long int time_calendar_;
157  long long int time_thread_cputime_;
158  };
159 public:
165  Profile(const std::string& name = "profile") :
166  name_(name),
167  start_time_calendar_(gu_time_calendar()),
168  start_time_thread_cputime_(gu_time_thread_cputime()),
169  points_()
170  { }
171 
172  void enter(const Point& point) const
173  {
174  points_[point.key_].count_++;
175  point.enter_time_calendar_ = gu_time_calendar();
176  point.enter_time_thread_cputime_ = gu_time_thread_cputime();
177  }
178 
179  void leave(const Point& point) const
180  {
181  long long int t_cal(gu_time_calendar());
182  long long int t_thdcpu(gu_time_thread_cputime());
183  points_[point.key_].time_calendar_ +=
184  (t_cal - point.enter_time_calendar_);
185  points_[point.key_].time_thread_cputime_ +=
186  (t_thdcpu - point.enter_time_thread_cputime_);
187  }
188 
189  void clear() { points_.clear(); }
190 
191  friend std::ostream& operator<<(std::ostream&, const Profile&);
192 
193  typedef std::map<Key, PointStats> Map;
194  std::string const name_;
195  long long int const start_time_calendar_;
196  long long int const start_time_thread_cputime_;
197  mutable Map points_;
198 };
199 
200 inline prof::Point::Point(const Profile& prof,
201  const char* file,
202  const char* func,
203  const int line) :
204  prof_(prof),
205  key_(file, func, line),
206  enter_time_calendar_(),
207  enter_time_thread_cputime_()
208 {
209  prof_.enter(*this);
210 }
211 
212 inline prof::Point::~Point()
213 {
214  prof_.leave(*this);
215 }
216 
217 
221 inline std::ostream& prof::operator<<(std::ostream& os, const Profile& prof)
222 {
223  Profile::PointStats cumul;
224 
225  char prev_fill(os.fill());
226  os.fill(' ');
227  os << "\nprofile name: " << prof.name_;
228 
229 
230  os << std::left << std::fixed << std::setprecision(3);
231  os << "\n\n";
232  os << std::setw(40) << "point";
233  os << std::setw(10) << "count";
234  os << std::setw(10) << "calendar";
235  os << std::setw(10) << "cpu";
236  os << "\n"
237  << std::setfill('-') << std::setw(70) << ""
238  << std::setfill(' ') << "\n";
239  for (Profile::Map::const_iterator i = prof.points_.begin();
240  i != prof.points_.end(); ++i)
241  {
242  os << std::setw(40) << std::left << i->first.to_string();
243  os << std::right;
244  os << std::setw(10) << i->second.count_;
245  os << std::setw(10) << double(i->second.time_calendar_)*1.e-9;
246  os << std::setw(10) << double(i->second.time_thread_cputime_)*1.e-9;
247  os << std::left;
248  os << "\n";
249  cumul = cumul + i->second;
250  }
251 
252  os << "\ntot count : " << cumul.count_;
253  os << "\ntot calendar time : " << double(cumul.time_calendar_)*1.e-9;
254  os << "\ntot thread cputime: " << double(cumul.time_thread_cputime_)*1.e-9;
255  os << "\ntot ct since ctor : "
256  << double(gu::datetime::Date::now().get_utc()
257  - prof.start_time_calendar_)*1.e-9;
258 
259  os.fill(prev_fill);
260  return os;
261 }
262 
263 
264 /*
265  * Convenience macros for defining profile entry and leave points.
266  * If GCOMM_PROFILE is undefined, these macros expand to no-op.
267  */
268 #ifdef GCOMM_PROFILE
269 #define profile_enter(__p) do { \
270  const prof::Point __point((__p), __FILE__, __FUNCTION__, __LINE__); \
271 
272 #define profile_leave(__p) \
273  } while (0)
274 #else
275 #define profile_enter(__p)
276 #define profile_leave(__p)
277 #endif // GCOMM_PROFILE
278 
279 #endif // GCOMM_PROFILE_HPP
Definition: profile.hpp:136
Profile(const std::string &name="profile")
Definition: profile.hpp:165
Definition: profile.hpp:71
Definition: profile.hpp:117