Thursday, August 4, 2011

Code Profiling classes

A simple code profiling class that will profile for the entry point "TIME()" to the closing curly "}". Enjoy

#include <iostream>
#include <iomanip>
#include <list>
#include <time.h>
#include <math.h>

//test header
#include <unistd.h> 
#include <stdlib.h>

class TimerStats
{
public:
    typedef std::list<TimerStats*> TimerStatsList;
    typedef time_t                 TimeUnit;

    static TimerStatsList& statsList()
    {
        static TimerStatsList list;
        return list;
    }

    static void printAll(std::ostream& out)
    {
        TimerStatsList::iterator it;
        for(it  =  statsList().begin();
            it !=  statsList().end();
            it++)
        {
            out << *(*it);
        }
    }

    static TimeUnit getTime()
    {
        return time(NULL);
    }

    TimerStats(const char* file_, const uint32_t line_) : 
        file   (file_),
        line   (line_),
        count  (0),
        sum    (0),
        sum_sqr(0),
        max    (0),
        min    (0)
    {
        statsList().push_back(this);
    }
    
    void addValue(double val)
    {
        count++;
        sum += val;
        sum_sqr += (val*val);
        if (count == 1)
        {
            max = val;
            min = val;
        }
        else
        {
            max = max > val ? max : val;
            min = min < val ? min : val;
        }
    }
    
    const char*     file;
    const uint32_t  line;

    uint32_t      count;
    double        sum;
    double        sum_sqr;
    double        max;
    double        min;   

private:
    friend std::ostream& operator<<(std::ostream& out, TimerStats const& stats);
};

std::ostream& operator<<(std::ostream& out, TimerStats const& stats)
{
    double ave =0;
    double sdev=0;

    if (stats.count > 0) 
    {
        ave  = stats.sum/stats.count;
        sdev = stats.sum_sqr/stats.count - (ave*ave);
        sdev = sqrt(sdev);
    }

    out << " Count:"    << std::setw(10) << stats.count   
        << " Ave:"      << std::setw(10) << ave
        << " Sdev:"     << std::setw(10) << sdev
        << " Max:"      << std::setw(10) << stats.max     
        << " Min:"      << std::setw(10) << stats.min
        << " Total:"    << std::setw(10) << stats.sum
        << " " << stats.file << ":" << stats.line
        << "\n";

    return out;
}

class Timer
{
public:
    Timer(TimerStats& stats_) :
        stats(stats_),
        start(TimerStats::getTime())
    {}
        
    ~Timer() 
    { 
        stats.addValue(TimerStats::getTime()-start);
    }

private:
    TimerStats& stats;
    TimerStats::TimeUnit start;
};

#define TIME() static TimerStats stats##__LINE__(__FILE__,__LINE__); \
     Timer timer##__LINE__(stats##__LINE__)

int main(int argc, char const * const *argv)
{
    {
        TIME();
        
        for(int i= 0; i < 5; i++)
        {
            TIME();
            for(int j= 0; j < 5; j++)
            {
                TIME();
                // sleep(1);
                int k = rand() * rand();
                
                std::cout << k << "\n";
                while (k > 0) k--;
            }
        }
    }

    TimerStats::printAll(std::cout);
}

No comments:

Post a Comment