Skip to content

Instantly share code, notes, and snippets.

@vadz
Created April 27, 2014 16:26
Show Gist options
  • Save vadz/11349759 to your computer and use it in GitHub Desktop.
Save vadz/11349759 to your computer and use it in GitHub Desktop.
Trivial profiling helper for wxWidgets code
///////////////////////////////////////////////////////////////////////////////
// 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 <vadim@wxwidgets.org>
// 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