RCFProto
 All Classes Functions Typedefs
Profile.hpp
1 
2 //******************************************************************************
3 // RCF - Remote Call Framework
4 //
5 // Copyright (c) 2005 - 2013, Delta V Software. All rights reserved.
6 // http://www.deltavsoft.com
7 //
8 // RCF is distributed under dual licenses - closed source or GPL.
9 // Consult your particular license for conditions of use.
10 //
11 // If you have not purchased a commercial license, you are using RCF
12 // under GPL terms.
13 //
14 // Version: 2.0
15 // Contact: support <at> deltavsoft.com
16 //
17 //******************************************************************************
18 
19 #ifndef INCLUDE_UTIL_PROFILE_HPP
20 #define INCLUDE_UTIL_PROFILE_HPP
21 
22 #include <sys/types.h>
23 #include <sys/timeb.h>
24 
25 #include <iostream>
26 #include <map>
27 #include <memory>
28 #include <sstream>
29 #include <vector>
30 
31 #include "RCF/ThreadLibrary.hpp"
32 
33 namespace util {
34 
35  class ProfilingResults
36  {
37  private:
38  ProfilingResults()
39  {
40  }
41 
42  static ProfilingResults *&getSingletonPtrRef()
43  {
44  static ProfilingResults *pProfilingResults = NULL;
45  if (pProfilingResults == NULL)
46  {
47  pProfilingResults = new ProfilingResults();
48  }
49  return pProfilingResults;
50  }
51  public:
52  static ProfilingResults &getSingleton()
53  {
54  return *getSingletonPtrRef();
55  }
56  static void deleteSingleton()
57  {
58  delete getSingletonPtrRef();
59  getSingletonPtrRef() = NULL;
60  }
61  void dump()
62  {
63  RCF::Lock lock(mMutex);
64  for (unsigned int i=0; i<mResults.size(); i++)
65  {
66  std::ostringstream ostr;
67  ostr << "*************************\n";
68  ostr << "Profiling results for thread #" << i << ":\n";
69 
70  for (DataT::iterator iter_i = mResults[i]->begin(); iter_i != mResults[i]->end(); iter_i++) {
71  if (!(*iter_i).first.empty()) {
72  ostr << (*iter_i).first << ": " << (*iter_i).second.first / 1000.0 << " s.\n";
73  SubDataT &subData = (*iter_i).second.second;
74  for (SubDataT::iterator iter_j = subData.begin(); iter_j != subData.end(); iter_j++)
75  ostr << " " << (*iter_j).first << ": " << (*iter_j).second / 1000.0 << "s.\n";
76  }
77  }
78 
79  ostr << "*************************\n";
80  std::cout << ostr.str();
81  }
82  }
83 
84  private:
85  friend class ProfilingData;
86  typedef std::map<std::string, unsigned int> SubDataT;
87  typedef std::map<std::string, std::pair<unsigned int, SubDataT > > DataT;
88 
89  RCF::Mutex mMutex;
90  std::vector< DataT * > mResults;
91 
92  void add( DataT *data )
93  {
94  RCF::Lock scoped_lock( mMutex );
95  mResults.push_back( data );
96  }
97 
98  };
99 
100  class ProfilingData
101  {
102  private:
103  ProfilingData() : stack_(100), data_(new DataT()) { ProfilingResults::getSingleton().add( data_ ); }
104  public:
105  static ProfilingData &getThreadSpecificInstance()
106  {
107  static RCF::ThreadSpecificPtr<ProfilingData>::Val profilingData;
108 
109  if (NULL == profilingData.get())
110  {
111  profilingData.reset(new ProfilingData());
112  profilingData->push("");
113  }
114  return *profilingData;
115  }
116 
117  void push(std::string sz)
118  {
119  stack_.push_back(sz);
120  }
121 
122  void pop()
123  {
124  stack_.pop_back();
125  }
126 
127  void add(unsigned int timespan)
128  {
129  std::string cur = stack_[stack_.size()-1];
130  std::string prev = stack_[stack_.size()-2];
131  (*data_)[cur].first += timespan;
132  (*data_)[prev].second[cur] += timespan;
133  }
134 
135  private:
136  typedef ProfilingResults::DataT DataT;
137  std::vector<std::string> stack_;
138  DataT *data_;
139  };
140 
141  inline unsigned int getTickCount()
142  {
143  return RCF::getCurrentTimeMs();
144  }
145 
146  class Profile
147  {
148  public:
149  Profile(const std::string &name) : name(name), t0(getTickCount()), t1(0)
150  {
151  ProfilingData::getThreadSpecificInstance().push(name);
152  }
153 
154  void stop()
155  {
156  t1 = getTickCount();
157  ProfilingData::getThreadSpecificInstance().add(t1 - t0);
158  ProfilingData::getThreadSpecificInstance().pop();
159  }
160 
161 
162  ~Profile()
163  {
164  if (!t1)
165  {
166  stop();
167  }
168  }
169 
170  int getDurationMs()
171  {
172  RCF_ASSERT(t1);
173  return t1 - t0;
174  }
175 
176  private:
177  std::string name;
178  unsigned int t0;
179  unsigned int t1;
180  };
181 
182  class ImmediateProfile
183  {
184  public:
185  ImmediateProfile(const std::string &name) :
186  mName(name),
187  t0Ms(getTickCount()),
188  t1Ms()
189  {}
190 
191  ~ImmediateProfile()
192  {
193  t1Ms = getTickCount();
194  std::ostringstream ostr;
195  ostr << "Profile result: " << mName << ": " << t1Ms-t0Ms << "ms" << std::endl;
196  std::cout << ostr.str();
197  }
198 
199  private:
200  std::string mName;
201  unsigned int t0Ms;
202  unsigned int t1Ms;
203  };
204 
205 } // namespace util
206 
207 #endif