Chris@49
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@0
|
2
|
Chris@0
|
3 /*
|
Chris@52
|
4 Sonic Visualiser
|
Chris@52
|
5 An audio file viewer and annotation editor.
|
Chris@52
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@0
|
7
|
Chris@52
|
8 This program is free software; you can redistribute it and/or
|
Chris@52
|
9 modify it under the terms of the GNU General Public License as
|
Chris@52
|
10 published by the Free Software Foundation; either version 2 of the
|
Chris@52
|
11 License, or (at your option) any later version. See the file
|
Chris@52
|
12 COPYING included with this distribution for more information.
|
Chris@0
|
13 */
|
Chris@0
|
14
|
Chris@0
|
15 /*
|
Chris@0
|
16 This is a modified version of a source file from the
|
Chris@0
|
17 Rosegarden MIDI and audio sequencer and notation editor.
|
Chris@17
|
18 This file copyright 2000-2006 Chris Cannam and Guillaume Laurent.
|
Chris@0
|
19 */
|
Chris@0
|
20
|
Chris@0
|
21 #include <iostream>
|
Chris@0
|
22 #include "Profiler.h"
|
Chris@0
|
23
|
Chris@0
|
24 #include <vector>
|
Chris@0
|
25 #include <algorithm>
|
Chris@0
|
26
|
Chris@0
|
27 //#define NO_TIMING 1
|
Chris@0
|
28
|
Chris@135
|
29 #define WANT_TIMING 1
|
Chris@135
|
30
|
Chris@0
|
31 #ifdef NDEBUG
|
Chris@135
|
32 #ifndef WANT_TIMING
|
Chris@0
|
33 #define NO_TIMING 1
|
Chris@0
|
34 #endif
|
Chris@135
|
35 #endif
|
Chris@0
|
36
|
Chris@0
|
37 using std::cerr;
|
Chris@0
|
38 using std::endl;
|
Chris@0
|
39
|
Chris@0
|
40 Profiles* Profiles::m_instance = 0;
|
Chris@0
|
41
|
Chris@0
|
42 Profiles* Profiles::getInstance()
|
Chris@0
|
43 {
|
Chris@0
|
44 if (!m_instance) m_instance = new Profiles();
|
Chris@0
|
45
|
Chris@0
|
46 return m_instance;
|
Chris@0
|
47 }
|
Chris@0
|
48
|
Chris@0
|
49 Profiles::Profiles()
|
Chris@0
|
50 {
|
Chris@0
|
51 }
|
Chris@0
|
52
|
Chris@0
|
53 Profiles::~Profiles()
|
Chris@0
|
54 {
|
Chris@0
|
55 dump();
|
Chris@0
|
56 }
|
Chris@0
|
57
|
Chris@0
|
58 void Profiles::accumulate(const char* id, clock_t time, RealTime rt)
|
Chris@0
|
59 {
|
Chris@0
|
60 #ifndef NO_TIMING
|
Chris@0
|
61 ProfilePair &pair(m_profiles[id]);
|
Chris@0
|
62 ++pair.first;
|
Chris@0
|
63 pair.second.first += time;
|
Chris@0
|
64 pair.second.second = pair.second.second + rt;
|
Chris@0
|
65
|
Chris@0
|
66 TimePair &timePair(m_lastCalls[id]);
|
Chris@0
|
67 timePair.first = time;
|
Chris@0
|
68 timePair.second = rt;
|
Chris@0
|
69 #endif
|
Chris@0
|
70 }
|
Chris@0
|
71
|
Chris@0
|
72 void Profiles::dump()
|
Chris@0
|
73 {
|
Chris@0
|
74 #ifndef NO_TIMING
|
Chris@0
|
75 cerr << "Profiles::dump() :\n";
|
Chris@0
|
76
|
Chris@0
|
77 // I'm finding these two confusing dumped out in random order,
|
Chris@0
|
78 // so I'm going to sort them alphabetically:
|
Chris@0
|
79
|
Chris@0
|
80 std::vector<const char *> profileNames;
|
Chris@0
|
81 for (ProfileMap::iterator i = m_profiles.begin();
|
Chris@0
|
82 i != m_profiles.end(); ++i) {
|
Chris@0
|
83 profileNames.push_back((*i).first);
|
Chris@0
|
84 }
|
Chris@0
|
85
|
Chris@0
|
86 std::sort(profileNames.begin(), profileNames.end());
|
Chris@0
|
87
|
Chris@0
|
88 for (std::vector<const char *>::iterator i = profileNames.begin();
|
Chris@0
|
89 i != profileNames.end(); ++i) {
|
Chris@0
|
90
|
Chris@0
|
91 cerr << "-> " << *i << ": CPU: "
|
Chris@0
|
92 << m_profiles[*i].first << " calls, "
|
Chris@0
|
93 << int((m_profiles[*i].second.first * 1000.0) / CLOCKS_PER_SEC) << "ms, "
|
Chris@0
|
94 << (((double)m_profiles[*i].second.first * 1000000.0 /
|
Chris@0
|
95 (double)m_profiles[*i].first) / CLOCKS_PER_SEC) << "us/call"
|
Chris@0
|
96 << endl;
|
Chris@0
|
97
|
Chris@0
|
98 cerr << "-> " << *i << ": real: "
|
Chris@0
|
99 << m_profiles[*i].first << " calls, "
|
Chris@0
|
100 << m_profiles[*i].second.second << ", "
|
Chris@0
|
101 << (m_profiles[*i].second.second / m_profiles[*i].first)
|
Chris@0
|
102 << "/call"
|
Chris@0
|
103 << endl;
|
Chris@0
|
104
|
Chris@0
|
105 cerr << "-> " << *i << ": last: CPU: "
|
Chris@0
|
106 << int((m_lastCalls[*i].first * 1000.0) / CLOCKS_PER_SEC) << "ms, "
|
Chris@0
|
107 << " real: "
|
Chris@0
|
108 << m_lastCalls[*i].second << endl;
|
Chris@0
|
109 }
|
Chris@0
|
110
|
Chris@0
|
111 cerr << "Profiles::dump() finished\n";
|
Chris@0
|
112 #endif
|
Chris@0
|
113 }
|
Chris@0
|
114
|
Chris@0
|
115 Profiler::Profiler(const char* c, bool showOnDestruct)
|
Chris@0
|
116 : m_c(c),
|
Chris@0
|
117 m_showOnDestruct(showOnDestruct)
|
Chris@0
|
118 {
|
Chris@0
|
119 #ifndef NO_TIMING
|
Chris@0
|
120 m_startCPU = clock();
|
Chris@0
|
121
|
Chris@0
|
122 struct timeval tv;
|
Chris@0
|
123 (void)gettimeofday(&tv, 0);
|
Chris@26
|
124 m_startTime = RealTime::fromTimeval(tv);
|
Chris@0
|
125 #endif
|
Chris@0
|
126 }
|
Chris@0
|
127
|
Chris@0
|
128 void
|
Chris@0
|
129 Profiler::update()
|
Chris@0
|
130 {
|
Chris@0
|
131 #ifndef NO_TIMING
|
Chris@0
|
132 clock_t elapsedCPU = clock() - m_startCPU;
|
Chris@0
|
133
|
Chris@0
|
134 struct timeval tv;
|
Chris@0
|
135 (void)gettimeofday(&tv, 0);
|
Chris@26
|
136 RealTime elapsedTime = RealTime::fromTimeval(tv) - m_startTime;
|
Chris@0
|
137
|
Chris@0
|
138 cerr << "Profiler : id = " << m_c
|
Chris@0
|
139 << " - elapsed so far = " << ((elapsedCPU * 1000) / CLOCKS_PER_SEC)
|
Chris@0
|
140 << "ms CPU, " << elapsedTime << " real" << endl;
|
Chris@0
|
141 #endif
|
Chris@0
|
142 }
|
Chris@0
|
143
|
Chris@0
|
144 Profiler::~Profiler()
|
Chris@0
|
145 {
|
Chris@0
|
146 #ifndef NO_TIMING
|
Chris@0
|
147 clock_t elapsedCPU = clock() - m_startCPU;
|
Chris@0
|
148
|
Chris@0
|
149 struct timeval tv;
|
Chris@0
|
150 (void)gettimeofday(&tv, 0);
|
Chris@26
|
151 RealTime elapsedTime = RealTime::fromTimeval(tv) - m_startTime;
|
Chris@0
|
152
|
Chris@0
|
153 Profiles::getInstance()->accumulate(m_c, elapsedCPU, elapsedTime);
|
Chris@0
|
154
|
Chris@0
|
155 if (m_showOnDestruct)
|
Chris@0
|
156 cerr << "Profiler : id = " << m_c
|
Chris@0
|
157 << " - elapsed = " << ((elapsedCPU * 1000) / CLOCKS_PER_SEC)
|
Chris@0
|
158 << "ms CPU, " << elapsedTime << " real" << endl;
|
Chris@0
|
159 #endif
|
Chris@0
|
160 }
|
Chris@0
|
161
|