annotate base/Profiler.cpp @ 537:3cc4b7cd2aa5

* Merge from one-fftdataserver-per-fftmodel branch. This bit of reworking (which is not described very accurately by the title of the branch) turns the MatrixFile object into something that either reads or writes, but not both, and separates the FFT file cache reader and writer implementations separately. This allows the FFT data server to have a single thread owning writers and one reader per "customer" thread, and for all locking to be vastly simplified and concentrated in the data server alone (because none of the classes it makes use of is used in more than one thread at a time). The result is faster and more trustworthy code.
author Chris Cannam
date Tue, 27 Jan 2009 13:25:10 +0000
parents 115f60df1e4d
children 29efe322ab47
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@202 18 This file copyright 2000-2006 Chris Cannam, Guillaume Laurent,
Chris@202 19 and QMUL.
Chris@0 20 */
Chris@0 21
Chris@0 22 #include <iostream>
Chris@0 23 #include "Profiler.h"
Chris@0 24
Chris@0 25 #include <vector>
Chris@0 26 #include <algorithm>
Chris@183 27 #include <set>
Chris@183 28 #include <map>
Chris@0 29
Chris@0 30 using std::cerr;
Chris@0 31 using std::endl;
Chris@0 32
Chris@0 33 Profiles* Profiles::m_instance = 0;
Chris@0 34
Chris@0 35 Profiles* Profiles::getInstance()
Chris@0 36 {
Chris@0 37 if (!m_instance) m_instance = new Profiles();
Chris@0 38
Chris@0 39 return m_instance;
Chris@0 40 }
Chris@0 41
Chris@0 42 Profiles::Profiles()
Chris@0 43 {
Chris@0 44 }
Chris@0 45
Chris@0 46 Profiles::~Profiles()
Chris@0 47 {
Chris@0 48 dump();
Chris@0 49 }
Chris@0 50
Chris@259 51 void Profiles::accumulate(
Chris@259 52 #ifndef NO_TIMING
Chris@259 53 const char* id, clock_t time, RealTime rt
Chris@259 54 #else
Chris@259 55 const char*, clock_t, RealTime
Chris@259 56 #endif
Chris@259 57 )
Chris@0 58 {
Chris@0 59 #ifndef NO_TIMING
Chris@0 60 ProfilePair &pair(m_profiles[id]);
Chris@0 61 ++pair.first;
Chris@0 62 pair.second.first += time;
Chris@0 63 pair.second.second = pair.second.second + rt;
Chris@0 64
Chris@183 65 TimePair &lastPair(m_lastCalls[id]);
Chris@183 66 lastPair.first = time;
Chris@183 67 lastPair.second = rt;
Chris@183 68
Chris@183 69 TimePair &worstPair(m_worstCalls[id]);
Chris@183 70 if (time > worstPair.first) {
Chris@183 71 worstPair.first = time;
Chris@183 72 }
Chris@183 73 if (rt > worstPair.second) {
Chris@183 74 worstPair.second = rt;
Chris@183 75 }
Chris@0 76 #endif
Chris@0 77 }
Chris@0 78
Chris@183 79 void Profiles::dump() const
Chris@0 80 {
Chris@183 81 #ifndef NO_TIMING
Chris@0 82
Chris@183 83 fprintf(stderr, "Profiling points:\n");
Chris@0 84
Chris@183 85 fprintf(stderr, "\nBy name:\n");
Chris@183 86
Chris@183 87 typedef std::set<const char *, std::less<std::string> > StringSet;
Chris@183 88
Chris@183 89 StringSet profileNames;
Chris@183 90 for (ProfileMap::const_iterator i = m_profiles.begin();
Chris@183 91 i != m_profiles.end(); ++i) {
Chris@183 92 profileNames.insert(i->first);
Chris@0 93 }
Chris@0 94
Chris@183 95 for (StringSet::const_iterator i = profileNames.begin();
Chris@183 96 i != profileNames.end(); ++i) {
Chris@0 97
Chris@183 98 ProfileMap::const_iterator j = m_profiles.find(*i);
Chris@0 99
Chris@183 100 if (j == m_profiles.end()) continue;
Chris@0 101
Chris@183 102 const ProfilePair &pp(j->second);
Chris@0 103
Chris@183 104 fprintf(stderr, "%s(%d):\n", *i, pp.first);
Chris@183 105
Chris@183 106 fprintf(stderr, "\tCPU: \t%.9g ms/call \t[%d ms total]\n",
Chris@183 107 (((double)pp.second.first * 1000.0 /
Chris@183 108 (double)pp.first) / CLOCKS_PER_SEC),
Chris@183 109 int((pp.second.first * 1000.0) / CLOCKS_PER_SEC));
Chris@183 110
Chris@183 111 fprintf(stderr, "\tReal: \t%s ms \t[%s ms total]\n",
Chris@183 112 ((pp.second.second / pp.first) * 1000).toString().c_str(),
Chris@183 113 (pp.second.second * 1000).toString().c_str());
Chris@183 114
Chris@183 115 WorstCallMap::const_iterator k = m_worstCalls.find(*i);
Chris@183 116 if (k == m_worstCalls.end()) continue;
Chris@183 117
Chris@183 118 const TimePair &wc(k->second);
Chris@183 119
Chris@183 120 fprintf(stderr, "\tWorst:\t%s ms/call \t[%d ms CPU]\n",
Chris@183 121 (wc.second * 1000).toString().c_str(),
Chris@183 122 int((wc.first * 1000.0) / CLOCKS_PER_SEC));
Chris@0 123 }
Chris@0 124
Chris@183 125 typedef std::multimap<RealTime, const char *> TimeRMap;
Chris@183 126 typedef std::multimap<int, const char *> IntRMap;
Chris@183 127
Chris@183 128 TimeRMap totmap, avgmap, worstmap;
Chris@183 129 IntRMap ncallmap;
Chris@183 130
Chris@183 131 for (ProfileMap::const_iterator i = m_profiles.begin();
Chris@183 132 i != m_profiles.end(); ++i) {
Chris@183 133 totmap.insert(TimeRMap::value_type(i->second.second.second, i->first));
Chris@183 134 avgmap.insert(TimeRMap::value_type(i->second.second.second /
Chris@183 135 i->second.first, i->first));
Chris@183 136 ncallmap.insert(IntRMap::value_type(i->second.first, i->first));
Chris@183 137 }
Chris@183 138
Chris@183 139 for (WorstCallMap::const_iterator i = m_worstCalls.begin();
Chris@183 140 i != m_worstCalls.end(); ++i) {
Chris@183 141 worstmap.insert(TimeRMap::value_type(i->second.second,
Chris@183 142 i->first));
Chris@183 143 }
Chris@183 144
Chris@183 145
Chris@183 146 fprintf(stderr, "\nBy total:\n");
Chris@183 147 for (TimeRMap::const_iterator i = totmap.end(); i != totmap.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 average:\n");
Chris@183 154 for (TimeRMap::const_iterator i = avgmap.end(); i != avgmap.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());
Chris@183 158 }
Chris@183 159
Chris@183 160 fprintf(stderr, "\nBy worst case:\n");
Chris@183 161 for (TimeRMap::const_iterator i = worstmap.end(); i != worstmap.begin(); ) {
Chris@183 162 --i;
Chris@183 163 fprintf(stderr, "%-40s %s ms\n", i->second,
Chris@408 164 (i->first * 1000).toString().c_str());
Chris@183 165 }
Chris@183 166
Chris@183 167 fprintf(stderr, "\nBy number of calls:\n");
Chris@183 168 for (IntRMap::const_iterator i = ncallmap.end(); i != ncallmap.begin(); ) {
Chris@183 169 --i;
Chris@183 170 fprintf(stderr, "%-40s %d\n", i->second, i->first);
Chris@183 171 }
Chris@183 172
Chris@0 173 #endif
Chris@0 174 }
Chris@0 175
Chris@183 176 #ifndef NO_TIMING
Chris@183 177
Chris@408 178 Profiler::Profiler(const char* c, bool showOnDestruct) :
Chris@408 179 m_c(c),
Chris@408 180 m_showOnDestruct(showOnDestruct),
Chris@408 181 m_ended(false)
Chris@0 182 {
Chris@0 183 m_startCPU = clock();
Chris@0 184
Chris@0 185 struct timeval tv;
Chris@0 186 (void)gettimeofday(&tv, 0);
Chris@26 187 m_startTime = RealTime::fromTimeval(tv);
Chris@0 188 }
Chris@0 189
Chris@0 190 void
Chris@183 191 Profiler::update() const
Chris@0 192 {
Chris@0 193 clock_t elapsedCPU = clock() - m_startCPU;
Chris@0 194
Chris@0 195 struct timeval tv;
Chris@0 196 (void)gettimeofday(&tv, 0);
Chris@26 197 RealTime elapsedTime = RealTime::fromTimeval(tv) - m_startTime;
Chris@0 198
Chris@0 199 cerr << "Profiler : id = " << m_c
Chris@0 200 << " - elapsed so far = " << ((elapsedCPU * 1000) / CLOCKS_PER_SEC)
Chris@0 201 << "ms CPU, " << elapsedTime << " real" << endl;
Chris@0 202 }
Chris@0 203
Chris@0 204 Profiler::~Profiler()
Chris@0 205 {
Chris@408 206 if (!m_ended) end();
Chris@408 207 }
Chris@408 208
Chris@408 209 void
Chris@408 210 Profiler::end()
Chris@408 211 {
Chris@0 212 clock_t elapsedCPU = clock() - m_startCPU;
Chris@0 213
Chris@0 214 struct timeval tv;
Chris@0 215 (void)gettimeofday(&tv, 0);
Chris@26 216 RealTime elapsedTime = RealTime::fromTimeval(tv) - m_startTime;
Chris@0 217
Chris@0 218 Profiles::getInstance()->accumulate(m_c, elapsedCPU, elapsedTime);
Chris@0 219
Chris@0 220 if (m_showOnDestruct)
Chris@0 221 cerr << "Profiler : id = " << m_c
Chris@0 222 << " - elapsed = " << ((elapsedCPU * 1000) / CLOCKS_PER_SEC)
Chris@0 223 << "ms CPU, " << elapsedTime << " real" << endl;
Chris@408 224
Chris@408 225 m_ended = true;
Chris@0 226 }
Chris@0 227
Chris@183 228 #endif
Chris@183 229