Created
April 27, 2014 16:26
-
-
Save vadz/11349759 to your computer and use it in GitHub Desktop.
Trivial profiling helper for wxWidgets code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/////////////////////////////////////////////////////////////////////////////// | |
// Name: wx/profile.h | |
// Purpose: Simple helprs for manually profiling the code. | |
// Author: Vadim Zeitlin | |
// Created: 2013-02-22 | |
// RCS-ID: $Id$ | |
// Copyright: (c) 2013 Vadim Zeitlin <[email protected]> | |
// Licence: wxWindows licence | |
/////////////////////////////////////////////////////////////////////////////// | |
#ifndef _WX_PROFILE_H_ | |
#define _WX_PROFILE_H_ | |
#include "wx/cpp.h" | |
#include "wx/math.h" | |
#include "wx/msgout.h" | |
#include "wx/stopwatch.h" | |
// ---------------------------------------------------------------------------- | |
// Class containing the results of profiling the given block. | |
// ---------------------------------------------------------------------------- | |
// This class is used with wxBlockProfile and collects information about the | |
// block of code it appears in. Objects of this class are normally declared as | |
// static variables and simply dump the results when they're destroyed on | |
// program exit. | |
class wxBlockProfileResults | |
{ | |
public: | |
wxBlockProfileResults(const char* name) | |
: m_name(name) | |
{ | |
m_n = 0; | |
// No need to initialize the rest, this is done in AddResult(). | |
} | |
~wxBlockProfileResults() | |
{ | |
if ( m_n ) | |
{ | |
wxMessageOutputDebug().Printf( | |
"Block \"%s\": executed %lu times, %.0fus avg, %.0f std dev" | |
" (%.0f/%.0f min/max)", | |
m_name, | |
m_n, | |
m_M, | |
m_n == 1 ? 0. : sqrt(m_S/(m_n - 1)), | |
m_min.ToDouble(), | |
m_max.ToDouble() | |
); | |
} | |
} | |
private: | |
// This method is called on block exit by wxBlockProfiler only, hence | |
// they're private and that class is our friend. | |
void AddResult(wxLongLong timeSpent) | |
{ | |
// We use the algorithm for iteratively computing the mean and the | |
// standard deviation of the sequence of values described in Knuth's | |
// "The Art of Computer Programming, Volume 2: Seminumerical | |
// Algorithms", section 4.2.2. | |
// | |
// The algorithm defines the sequences M(k) and S(k) as follows: | |
// | |
// M(1) = x(1), M(k) = M(k-1) + (x(k) - M(k-1)) / k | |
// S(1) = 0, S(k) = S(k-1) + (x(k) - M(k-1))*(x(k) - M(k)) | |
// | |
// where x(k) is the k-th value. Then the mean is simply the last value | |
// of the first sequence M(N) and the standard deviation is | |
// sqrt(S(N)/(N-1)). | |
const double x = timeSpent.ToDouble(); | |
if ( !m_n++ ) | |
{ | |
m_min = | |
m_max = timeSpent; | |
m_M = x; | |
m_S = 0; | |
} | |
else | |
{ | |
if ( timeSpent < m_min ) | |
m_min = timeSpent; | |
if ( timeSpent > m_max ) | |
m_max = timeSpent; | |
const double lastM = m_M; | |
m_M += (x - lastM) / m_n; | |
m_S += (x - lastM)*(x - m_M); | |
} | |
} | |
friend class wxBlockProfiler; | |
// The user-specified name of the block. | |
const char* const m_name; | |
// The number of times the block was executed so far. | |
unsigned long m_n; | |
// The minimal and maximal amount of time the block ran. | |
wxLongLong m_min, | |
m_max; | |
// The current values of M and S series we use to incrementally compute the | |
// mean and the standard deviation, see the comment in AddResult(). | |
double m_M, m_S; | |
wxDECLARE_NO_COPY_CLASS(wxBlockProfileResults); | |
}; | |
class wxBlockProfiler : public wxStopWatch | |
{ | |
public: | |
wxBlockProfiler(wxBlockProfileResults& results) | |
: m_results(results) | |
{ | |
} | |
~wxBlockProfiler() | |
{ | |
m_results.AddResult(TimeInMicro()); | |
} | |
private: | |
wxBlockProfileResults& m_results; | |
wxDECLARE_NO_COPY_CLASS(wxBlockProfiler); | |
}; | |
#define wxPROFILE_NAMED_BLOCK(name) \ | |
static wxBlockProfileResults wxTheBlockProfileResults(name); \ | |
wxBlockProfiler wxMAKE_UNIQUE_NAME(wxBlockProfiler)(wxTheBlockProfileResults) | |
#define wxPROFILE_BLOCK() wxPROFILE_NAMED_BLOCK(__WXFUNCTION__) | |
#endif // _WX_PROFILE_H_ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment