Profiler.cpp

Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     
00008     This program is free software; you can redistribute it and/or
00009     modify it under the terms of the GNU General Public License as
00010     published by the Free Software Foundation; either version 2 of the
00011     License, or (at your option) any later version.  See the file
00012     COPYING included with this distribution for more information.
00013 */
00014 
00015 /*
00016    This is a modified version of a source file from the 
00017    Rosegarden MIDI and audio sequencer and notation editor.
00018    This file copyright 2000-2006 Chris Cannam, Guillaume Laurent,
00019    and QMUL.
00020 */
00021 
00022 #include <iostream>
00023 #include "Profiler.h"
00024 
00025 #include <vector>
00026 #include <algorithm>
00027 #include <set>
00028 #include <map>
00029 
00030 using std::cerr;
00031 using std::endl;
00032 
00033 Profiles* Profiles::m_instance = 0;
00034 
00035 Profiles* Profiles::getInstance()
00036 {
00037     if (!m_instance) m_instance = new Profiles();
00038     
00039     return m_instance;
00040 }
00041 
00042 Profiles::Profiles()
00043 {
00044 }
00045 
00046 Profiles::~Profiles()
00047 {
00048     dump();
00049 }
00050 
00051 void Profiles::accumulate(
00052 #ifndef NO_TIMING
00053     const char* id, clock_t time, RealTime rt
00054 #else
00055     const char*, clock_t, RealTime
00056 #endif
00057 )
00058 {
00059 #ifndef NO_TIMING    
00060     ProfilePair &pair(m_profiles[id]);
00061     ++pair.first;
00062     pair.second.first += time;
00063     pair.second.second = pair.second.second + rt;
00064 
00065     TimePair &lastPair(m_lastCalls[id]);
00066     lastPair.first = time;
00067     lastPair.second = rt;
00068 
00069     TimePair &worstPair(m_worstCalls[id]);
00070     if (time > worstPair.first) {
00071         worstPair.first = time;
00072     }
00073     if (rt > worstPair.second) {
00074         worstPair.second = rt;
00075     }
00076 #endif
00077 }
00078 
00079 void Profiles::dump() const
00080 {
00081 #ifndef NO_TIMING
00082 
00083     fprintf(stderr, "Profiling points:\n");
00084 
00085     fprintf(stderr, "\nBy name:\n");
00086 
00087     typedef std::set<const char *, std::less<std::string> > StringSet;
00088 
00089     StringSet profileNames;
00090     for (ProfileMap::const_iterator i = m_profiles.begin();
00091          i != m_profiles.end(); ++i) {
00092         profileNames.insert(i->first);
00093     }
00094 
00095     for (StringSet::const_iterator i = profileNames.begin();
00096          i != profileNames.end(); ++i) {
00097 
00098         ProfileMap::const_iterator j = m_profiles.find(*i);
00099 
00100         if (j == m_profiles.end()) continue;
00101 
00102         const ProfilePair &pp(j->second);
00103 
00104         fprintf(stderr, "%s(%d):\n", *i, pp.first);
00105 
00106         fprintf(stderr, "\tCPU:  \t%.9g ms/call \t[%d ms total]\n",
00107                 (((double)pp.second.first * 1000.0 /
00108                   (double)pp.first) / CLOCKS_PER_SEC),
00109                 int((pp.second.first * 1000.0) / CLOCKS_PER_SEC));
00110 
00111         fprintf(stderr, "\tReal: \t%s ms      \t[%s ms total]\n",
00112                 ((pp.second.second / pp.first) * 1000).toString().c_str(),
00113                 (pp.second.second * 1000).toString().c_str());
00114 
00115         WorstCallMap::const_iterator k = m_worstCalls.find(*i);
00116         if (k == m_worstCalls.end()) continue;
00117         
00118         const TimePair &wc(k->second);
00119 
00120         fprintf(stderr, "\tWorst:\t%s ms/call \t[%d ms CPU]\n",
00121                 (wc.second * 1000).toString().c_str(),
00122                 int((wc.first * 1000.0) / CLOCKS_PER_SEC));
00123     }
00124 
00125     typedef std::multimap<RealTime, const char *> TimeRMap;
00126     typedef std::multimap<int, const char *> IntRMap;
00127     
00128     TimeRMap totmap, avgmap, worstmap;
00129     IntRMap ncallmap;
00130 
00131     for (ProfileMap::const_iterator i = m_profiles.begin();
00132          i != m_profiles.end(); ++i) {
00133         totmap.insert(TimeRMap::value_type(i->second.second.second, i->first));
00134         avgmap.insert(TimeRMap::value_type(i->second.second.second /
00135                                            i->second.first, i->first));
00136         ncallmap.insert(IntRMap::value_type(i->second.first, i->first));
00137     }
00138 
00139     for (WorstCallMap::const_iterator i = m_worstCalls.begin();
00140          i != m_worstCalls.end(); ++i) {
00141         worstmap.insert(TimeRMap::value_type(i->second.second,
00142                                              i->first));
00143     }
00144 
00145 
00146     fprintf(stderr, "\nBy total:\n");
00147     for (TimeRMap::const_iterator i = totmap.end(); i != totmap.begin(); ) {
00148         --i;
00149         fprintf(stderr, "%-40s  %s ms\n", i->second,
00150                 (i->first * 1000).toString().c_str());
00151     }
00152 
00153     fprintf(stderr, "\nBy average:\n");
00154     for (TimeRMap::const_iterator i = avgmap.end(); i != avgmap.begin(); ) {
00155         --i;
00156         fprintf(stderr, "%-40s  %s ms\n", i->second,
00157                 (i->first * 1000).toString().c_str());
00158     }
00159 
00160     fprintf(stderr, "\nBy worst case:\n");
00161     for (TimeRMap::const_iterator i = worstmap.end(); i != worstmap.begin(); ) {
00162         --i;
00163         fprintf(stderr, "%-40s  %s ms\n", i->second,
00164                 (i->first * 1000).toString().c_str(), i->second);
00165     }
00166 
00167     fprintf(stderr, "\nBy number of calls:\n");
00168     for (IntRMap::const_iterator i = ncallmap.end(); i != ncallmap.begin(); ) {
00169         --i;
00170         fprintf(stderr, "%-40s  %d\n", i->second, i->first);
00171     }
00172 
00173 #endif
00174 }
00175 
00176 #ifndef NO_TIMING    
00177 
00178 Profiler::Profiler(const char* c, bool showOnDestruct)
00179     : m_c(c),
00180       m_showOnDestruct(showOnDestruct)
00181 {
00182     m_startCPU = clock();
00183 
00184     struct timeval tv;
00185     (void)gettimeofday(&tv, 0);
00186     m_startTime = RealTime::fromTimeval(tv);
00187 }
00188 
00189 void
00190 Profiler::update() const
00191 {
00192     clock_t elapsedCPU = clock() - m_startCPU;
00193 
00194     struct timeval tv;
00195     (void)gettimeofday(&tv, 0);
00196     RealTime elapsedTime = RealTime::fromTimeval(tv) - m_startTime;
00197 
00198     cerr << "Profiler : id = " << m_c
00199          << " - elapsed so far = " << ((elapsedCPU * 1000) / CLOCKS_PER_SEC)
00200          << "ms CPU, " << elapsedTime << " real" << endl;
00201 }    
00202 
00203 Profiler::~Profiler()
00204 {
00205     clock_t elapsedCPU = clock() - m_startCPU;
00206 
00207     struct timeval tv;
00208     (void)gettimeofday(&tv, 0);
00209     RealTime elapsedTime = RealTime::fromTimeval(tv) - m_startTime;
00210 
00211     Profiles::getInstance()->accumulate(m_c, elapsedCPU, elapsedTime);
00212 
00213     if (m_showOnDestruct)
00214         cerr << "Profiler : id = " << m_c
00215              << " - elapsed = " << ((elapsedCPU * 1000) / CLOCKS_PER_SEC)
00216              << "ms CPU, " << elapsedTime << " real" << endl;
00217 }
00218  
00219 #endif
00220 

Generated on Wed Feb 20 15:45:27 2008 for SonicVisualiser by  doxygen 1.5.1