annotate base/Profiler.cpp @ 335:02d2ad95ea52 spectrogram-cache-rejig

* Get storage advice for each cache in an FFT data server. Allows us to be more confident about the actual memory situation and cut over from memory to disc part way through an FFT calculation if necessary. StorageAdviser is now a bit too optimistic though (it's too keen to allocate large numbers of small blocks in memory).
author Chris Cannam
date Tue, 13 Nov 2007 13:54:10 +0000
parents dc46851837d6
children 115f60df1e4d
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@183 164 (i->first * 1000).toString().c_str(), i->second);
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@0 178 Profiler::Profiler(const char* c, bool showOnDestruct)
Chris@0 179 : m_c(c),
Chris@0 180 m_showOnDestruct(showOnDestruct)
Chris@0 181 {
Chris@0 182 m_startCPU = clock();
Chris@0 183
Chris@0 184 struct timeval tv;
Chris@0 185 (void)gettimeofday(&tv, 0);
Chris@26 186 m_startTime = RealTime::fromTimeval(tv);
Chris@0 187 }
Chris@0 188
Chris@0 189 void
Chris@183 190 Profiler::update() const
Chris@0 191 {
Chris@0 192 clock_t elapsedCPU = clock() - m_startCPU;
Chris@0 193
Chris@0 194 struct timeval tv;
Chris@0 195 (void)gettimeofday(&tv, 0);
Chris@26 196 RealTime elapsedTime = RealTime::fromTimeval(tv) - m_startTime;
Chris@0 197
Chris@0 198 cerr << "Profiler : id = " << m_c
Chris@0 199 << " - elapsed so far = " << ((elapsedCPU * 1000) / CLOCKS_PER_SEC)
Chris@0 200 << "ms CPU, " << elapsedTime << " real" << endl;
Chris@0 201 }
Chris@0 202
Chris@0 203 Profiler::~Profiler()
Chris@0 204 {
Chris@0 205 clock_t elapsedCPU = clock() - m_startCPU;
Chris@0 206
Chris@0 207 struct timeval tv;
Chris@0 208 (void)gettimeofday(&tv, 0);
Chris@26 209 RealTime elapsedTime = RealTime::fromTimeval(tv) - m_startTime;
Chris@0 210
Chris@0 211 Profiles::getInstance()->accumulate(m_c, elapsedCPU, elapsedTime);
Chris@0 212
Chris@0 213 if (m_showOnDestruct)
Chris@0 214 cerr << "Profiler : id = " << m_c
Chris@0 215 << " - elapsed = " << ((elapsedCPU * 1000) / CLOCKS_PER_SEC)
Chris@0 216 << "ms CPU, " << elapsedTime << " real" << endl;
Chris@0 217 }
Chris@0 218
Chris@183 219 #endif
Chris@183 220