annotate base/Profiler.cpp @ 184:5a916fee6d2d

* Handle generator transforms (plugins whose channel count isn't dependent on number of audio inputs, as they have none) * Be less keen to suspend writing FFT data in spectrogram repaint -- only do it if we find we actually need to query the FFT data (i.e. we aren't repainting an area that hasn't been generated at all yet)
author Chris Cannam
date Tue, 10 Oct 2006 19:04:57 +0000
parents 146eb9e35baa
children 91fdc752e540
rev   line source
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@183 26 #include <set>
Chris@183 27 #include <map>
Chris@0 28
Chris@0 29 using std::cerr;
Chris@0 30 using std::endl;
Chris@0 31
Chris@0 32 Profiles* Profiles::m_instance = 0;
Chris@0 33
Chris@0 34 Profiles* Profiles::getInstance()
Chris@0 35 {
Chris@0 36 if (!m_instance) m_instance = new Profiles();
Chris@0 37
Chris@0 38 return m_instance;
Chris@0 39 }
Chris@0 40
Chris@0 41 Profiles::Profiles()
Chris@0 42 {
Chris@0 43 }
Chris@0 44
Chris@0 45 Profiles::~Profiles()
Chris@0 46 {
Chris@0 47 dump();
Chris@0 48 }
Chris@0 49
Chris@0 50 void Profiles::accumulate(const char* id, clock_t time, RealTime rt)
Chris@0 51 {
Chris@0 52 #ifndef NO_TIMING
Chris@0 53 ProfilePair &pair(m_profiles[id]);
Chris@0 54 ++pair.first;
Chris@0 55 pair.second.first += time;
Chris@0 56 pair.second.second = pair.second.second + rt;
Chris@0 57
Chris@183 58 TimePair &lastPair(m_lastCalls[id]);
Chris@183 59 lastPair.first = time;
Chris@183 60 lastPair.second = rt;
Chris@183 61
Chris@183 62 TimePair &worstPair(m_worstCalls[id]);
Chris@183 63 if (time > worstPair.first) {
Chris@183 64 worstPair.first = time;
Chris@183 65 }
Chris@183 66 if (rt > worstPair.second) {
Chris@183 67 worstPair.second = rt;
Chris@183 68 }
Chris@0 69 #endif
Chris@0 70 }
Chris@0 71
Chris@183 72 void Profiles::dump() const
Chris@0 73 {
Chris@183 74 #ifndef NO_TIMING
Chris@0 75
Chris@183 76 fprintf(stderr, "Profiling points:\n");
Chris@0 77
Chris@183 78 fprintf(stderr, "\nBy name:\n");
Chris@183 79
Chris@183 80 typedef std::set<const char *, std::less<std::string> > StringSet;
Chris@183 81
Chris@183 82 StringSet profileNames;
Chris@183 83 for (ProfileMap::const_iterator i = m_profiles.begin();
Chris@183 84 i != m_profiles.end(); ++i) {
Chris@183 85 profileNames.insert(i->first);
Chris@0 86 }
Chris@0 87
Chris@183 88 for (StringSet::const_iterator i = profileNames.begin();
Chris@183 89 i != profileNames.end(); ++i) {
Chris@0 90
Chris@183 91 ProfileMap::const_iterator j = m_profiles.find(*i);
Chris@0 92
Chris@183 93 if (j == m_profiles.end()) continue;
Chris@0 94
Chris@183 95 const ProfilePair &pp(j->second);
Chris@0 96
Chris@183 97 fprintf(stderr, "%s(%d):\n", *i, pp.first);
Chris@183 98
Chris@183 99 fprintf(stderr, "\tCPU: \t%.9g ms/call \t[%d ms total]\n",
Chris@183 100 (((double)pp.second.first * 1000.0 /
Chris@183 101 (double)pp.first) / CLOCKS_PER_SEC),
Chris@183 102 int((pp.second.first * 1000.0) / CLOCKS_PER_SEC));
Chris@183 103
Chris@183 104 fprintf(stderr, "\tReal: \t%s ms \t[%s ms total]\n",
Chris@183 105 ((pp.second.second / pp.first) * 1000).toString().c_str(),
Chris@183 106 (pp.second.second * 1000).toString().c_str());
Chris@183 107
Chris@183 108 WorstCallMap::const_iterator k = m_worstCalls.find(*i);
Chris@183 109 if (k == m_worstCalls.end()) continue;
Chris@183 110
Chris@183 111 const TimePair &wc(k->second);
Chris@183 112
Chris@183 113 fprintf(stderr, "\tWorst:\t%s ms/call \t[%d ms CPU]\n",
Chris@183 114 (wc.second * 1000).toString().c_str(),
Chris@183 115 int((wc.first * 1000.0) / CLOCKS_PER_SEC));
Chris@0 116 }
Chris@0 117
Chris@183 118 typedef std::multimap<RealTime, const char *> TimeRMap;
Chris@183 119 typedef std::multimap<int, const char *> IntRMap;
Chris@183 120
Chris@183 121 TimeRMap totmap, avgmap, worstmap;
Chris@183 122 IntRMap ncallmap;
Chris@183 123
Chris@183 124 for (ProfileMap::const_iterator i = m_profiles.begin();
Chris@183 125 i != m_profiles.end(); ++i) {
Chris@183 126 totmap.insert(TimeRMap::value_type(i->second.second.second, i->first));
Chris@183 127 avgmap.insert(TimeRMap::value_type(i->second.second.second /
Chris@183 128 i->second.first, i->first));
Chris@183 129 ncallmap.insert(IntRMap::value_type(i->second.first, i->first));
Chris@183 130 }
Chris@183 131
Chris@183 132 for (WorstCallMap::const_iterator i = m_worstCalls.begin();
Chris@183 133 i != m_worstCalls.end(); ++i) {
Chris@183 134 worstmap.insert(TimeRMap::value_type(i->second.second,
Chris@183 135 i->first));
Chris@183 136 }
Chris@183 137
Chris@183 138
Chris@183 139 fprintf(stderr, "\nBy total:\n");
Chris@183 140 for (TimeRMap::const_iterator i = totmap.end(); i != totmap.begin(); ) {
Chris@183 141 --i;
Chris@183 142 fprintf(stderr, "%-40s %s ms\n", i->second,
Chris@183 143 (i->first * 1000).toString().c_str());
Chris@183 144 }
Chris@183 145
Chris@183 146 fprintf(stderr, "\nBy average:\n");
Chris@183 147 for (TimeRMap::const_iterator i = avgmap.end(); i != avgmap.begin(); ) {
Chris@183 148 --i;
Chris@183 149 fprintf(stderr, "%-40s %s ms\n", i->second,
Chris@183 150 (i->first * 1000).toString().c_str());
Chris@183 151 }
Chris@183 152
Chris@183 153 fprintf(stderr, "\nBy worst case:\n");
Chris@183 154 for (TimeRMap::const_iterator i = worstmap.end(); i != worstmap.begin(); ) {
Chris@183 155 --i;
Chris@183 156 fprintf(stderr, "%-40s %s ms\n", i->second,
Chris@183 157 (i->first * 1000).toString().c_str(), i->second);
Chris@183 158 }
Chris@183 159
Chris@183 160 fprintf(stderr, "\nBy number of calls:\n");
Chris@183 161 for (IntRMap::const_iterator i = ncallmap.end(); i != ncallmap.begin(); ) {
Chris@183 162 --i;
Chris@183 163 fprintf(stderr, "%-40s %d\n", i->second, i->first);
Chris@183 164 }
Chris@183 165
Chris@0 166 #endif
Chris@0 167 }
Chris@0 168
Chris@183 169 #ifndef NO_TIMING
Chris@183 170
Chris@0 171 Profiler::Profiler(const char* c, bool showOnDestruct)
Chris@0 172 : m_c(c),
Chris@0 173 m_showOnDestruct(showOnDestruct)
Chris@0 174 {
Chris@0 175 m_startCPU = clock();
Chris@0 176
Chris@0 177 struct timeval tv;
Chris@0 178 (void)gettimeofday(&tv, 0);
Chris@26 179 m_startTime = RealTime::fromTimeval(tv);
Chris@0 180 }
Chris@0 181
Chris@0 182 void
Chris@183 183 Profiler::update() const
Chris@0 184 {
Chris@0 185 clock_t elapsedCPU = clock() - m_startCPU;
Chris@0 186
Chris@0 187 struct timeval tv;
Chris@0 188 (void)gettimeofday(&tv, 0);
Chris@26 189 RealTime elapsedTime = RealTime::fromTimeval(tv) - m_startTime;
Chris@0 190
Chris@0 191 cerr << "Profiler : id = " << m_c
Chris@0 192 << " - elapsed so far = " << ((elapsedCPU * 1000) / CLOCKS_PER_SEC)
Chris@0 193 << "ms CPU, " << elapsedTime << " real" << endl;
Chris@0 194 }
Chris@0 195
Chris@0 196 Profiler::~Profiler()
Chris@0 197 {
Chris@0 198 clock_t elapsedCPU = clock() - m_startCPU;
Chris@0 199
Chris@0 200 struct timeval tv;
Chris@0 201 (void)gettimeofday(&tv, 0);
Chris@26 202 RealTime elapsedTime = RealTime::fromTimeval(tv) - m_startTime;
Chris@0 203
Chris@0 204 Profiles::getInstance()->accumulate(m_c, elapsedCPU, elapsedTime);
Chris@0 205
Chris@0 206 if (m_showOnDestruct)
Chris@0 207 cerr << "Profiler : id = " << m_c
Chris@0 208 << " - elapsed = " << ((elapsedCPU * 1000) / CLOCKS_PER_SEC)
Chris@0 209 << "ms CPU, " << elapsedTime << " real" << endl;
Chris@0 210 }
Chris@0 211
Chris@183 212 #endif
Chris@183 213