svcore  1.9
Profiler.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2 of the
11  License, or (at your option) any later version. See the file
12  COPYING included with this distribution for more information.
13 */
14 
15 /*
16  This is a modified version of a source file from the
17  Rosegarden MIDI and audio sequencer and notation editor.
18  This file copyright 2000-2006 Chris Cannam, Guillaume Laurent,
19  and QMUL.
20 */
21 
22 #include <iostream>
23 #include "Profiler.h"
24 
25 #include <cstdio>
26 
27 #include <vector>
28 #include <algorithm>
29 #include <set>
30 #include <map>
31 
33 
35 {
36  if (!m_instance) m_instance = new Profiles();
37 
38  return m_instance;
39 }
40 
42 {
43 }
44 
46 {
47  dump();
48 }
49 
51 #ifndef NO_TIMING
52  const char* id, clock_t time, RealTime rt
53 #else
54  const char*, clock_t, RealTime
55 #endif
56 )
57 {
58 #ifndef NO_TIMING
59  ProfilePair &pair(m_profiles[id]);
60  ++pair.first;
61  pair.second.first += time;
62  pair.second.second = pair.second.second + rt;
63 
64  TimePair &lastPair(m_lastCalls[id]);
65  lastPair.first = time;
66  lastPair.second = rt;
67 
68  TimePair &worstPair(m_worstCalls[id]);
69  if (time > worstPair.first) {
70  worstPair.first = time;
71  }
72  if (rt > worstPair.second) {
73  worstPair.second = rt;
74  }
75 #endif
76 }
77 
78 void Profiles::dump() const
79 {
80 #ifndef NO_TIMING
81 
82  fprintf(stderr, "Profiling points:\n");
83 
84  fprintf(stderr, "\nBy name:\n");
85 
86  typedef std::set<const char *, std::less<std::string> > StringSet;
87 
88  StringSet profileNames;
89  for (ProfileMap::const_iterator i = m_profiles.begin();
90  i != m_profiles.end(); ++i) {
91  profileNames.insert(i->first);
92  }
93 
94  for (StringSet::const_iterator i = profileNames.begin();
95  i != profileNames.end(); ++i) {
96 
97  ProfileMap::const_iterator j = m_profiles.find(*i);
98 
99  if (j == m_profiles.end()) continue;
100 
101  const ProfilePair &pp(j->second);
102 
103  fprintf(stderr, "%s(%d):\n", *i, pp.first);
104 
105  fprintf(stderr, "\tCPU: \t%.9g ms/call \t[%d ms total]\n",
106  (((double)pp.second.first * 1000.0 /
107  (double)pp.first) / CLOCKS_PER_SEC),
108  int((pp.second.first * 1000.0) / CLOCKS_PER_SEC));
109 
110  fprintf(stderr, "\tReal: \t%s ms \t[%s ms total]\n",
111  ((pp.second.second / pp.first) * 1000).toString().c_str(),
112  (pp.second.second * 1000).toString().c_str());
113 
114  WorstCallMap::const_iterator k = m_worstCalls.find(*i);
115  if (k == m_worstCalls.end()) continue;
116 
117  const TimePair &wc(k->second);
118 
119  fprintf(stderr, "\tWorst:\t%s ms/call \t[%d ms CPU]\n",
120  (wc.second * 1000).toString().c_str(),
121  int((wc.first * 1000.0) / CLOCKS_PER_SEC));
122  }
123 
124  typedef std::multimap<RealTime, const char *> TimeRMap;
125  typedef std::multimap<int, const char *> IntRMap;
126 
127  TimeRMap totmap, avgmap, worstmap;
128  IntRMap ncallmap;
129 
130  for (ProfileMap::const_iterator i = m_profiles.begin();
131  i != m_profiles.end(); ++i) {
132  totmap.insert(TimeRMap::value_type(i->second.second.second, i->first));
133  avgmap.insert(TimeRMap::value_type(i->second.second.second /
134  i->second.first, i->first));
135  ncallmap.insert(IntRMap::value_type(i->second.first, i->first));
136  }
137 
138  for (WorstCallMap::const_iterator i = m_worstCalls.begin();
139  i != m_worstCalls.end(); ++i) {
140  worstmap.insert(TimeRMap::value_type(i->second.second,
141  i->first));
142  }
143 
144 
145  fprintf(stderr, "\nBy total:\n");
146  for (TimeRMap::const_iterator i = totmap.end(); i != totmap.begin(); ) {
147  --i;
148  fprintf(stderr, "%-40s %s ms\n", i->second,
149  (i->first * 1000).toString().c_str());
150  }
151 
152  fprintf(stderr, "\nBy average:\n");
153  for (TimeRMap::const_iterator i = avgmap.end(); i != avgmap.begin(); ) {
154  --i;
155  fprintf(stderr, "%-40s %s ms\n", i->second,
156  (i->first * 1000).toString().c_str());
157  }
158 
159  fprintf(stderr, "\nBy worst case:\n");
160  for (TimeRMap::const_iterator i = worstmap.end(); i != worstmap.begin(); ) {
161  --i;
162  fprintf(stderr, "%-40s %s ms\n", i->second,
163  (i->first * 1000).toString().c_str());
164  }
165 
166  fprintf(stderr, "\nBy number of calls:\n");
167  for (IntRMap::const_iterator i = ncallmap.end(); i != ncallmap.begin(); ) {
168  --i;
169  fprintf(stderr, "%-40s %d\n", i->second, i->first);
170  }
171 
172 #endif
173 }
174 
175 #ifndef NO_TIMING
176 
177 Profiler::Profiler(const char* c, bool showOnDestruct) :
178  m_c(c),
179  m_showOnDestruct(showOnDestruct),
180  m_ended(false)
181 {
182  m_startCPU = clock();
183 
184  struct timeval tv;
185  (void)gettimeofday(&tv, 0);
187 }
188 
189 void
191 {
192  clock_t elapsedCPU = clock() - m_startCPU;
193 
194  struct timeval tv;
195  (void)gettimeofday(&tv, 0);
196  RealTime elapsedTime = RealTime::fromTimeval(tv) - m_startTime;
197 
198  cerr << "Profiler : id = " << m_c
199  << " - elapsed so far = " << ((elapsedCPU * 1000) / CLOCKS_PER_SEC)
200  << "ms CPU, " << elapsedTime << " real" << endl;
201 }
202 
204 {
205  if (!m_ended) end();
206 }
207 
208 void
210 {
211  clock_t elapsedCPU = clock() - m_startCPU;
212 
213  struct timeval tv;
214  (void)gettimeofday(&tv, 0);
215  RealTime elapsedTime = RealTime::fromTimeval(tv) - m_startTime;
216 
217  Profiles::getInstance()->accumulate(m_c, elapsedCPU, elapsedTime);
218 
219  if (m_showOnDestruct)
220  cerr << "Profiler : id = " << m_c
221  << " - elapsed = " << ((elapsedCPU * 1000) / CLOCKS_PER_SEC)
222  << "ms CPU, " << elapsedTime << " real" << endl;
223 
224  m_ended = true;
225 }
226 
227 #endif
228 
static RealTime fromTimeval(const struct timeval &)
Definition: RealTime.cpp:72
void update() const
Definition: Profiler.cpp:190
WorstCallMap m_worstCalls
Definition: Profiler.h:72
Profiles()
Definition: Profiler.cpp:41
void end()
Definition: Profiler.cpp:209
std::pair< clock_t, RealTime > TimePair
Definition: Profiler.h:65
static Profiles * m_instance
Definition: Profiler.h:74
~Profiles()
Definition: Profiler.cpp:45
Profiling classes.
Definition: Profiler.h:53
const char * m_c
Definition: Profiler.h:104
bool m_ended
Definition: Profiler.h:108
RealTime m_startTime
Definition: Profiler.h:106
ProfileMap m_profiles
Definition: Profiler.h:70
LastCallMap m_lastCalls
Definition: Profiler.h:71
clock_t m_startCPU
Definition: Profiler.h:105
static Profiles * getInstance()
Definition: Profiler.cpp:34
std::pair< int, TimePair > ProfilePair
Definition: Profiler.h:66
Profiler(const char *name, bool showOnDestruct=false)
Create a profile point instance that records time consumed against the given profiling point name.
Definition: Profiler.cpp:177
void dump() const
Definition: Profiler.cpp:78
void accumulate(const char *id, clock_t time, RealTime rt)
Definition: Profiler.cpp:50
bool m_showOnDestruct
Definition: Profiler.h:107
RealTime represents time values to nanosecond precision with accurate arithmetic and frame-rate conve...
Definition: RealTime.h:35