audacia/src/Profiler.cpp

170 lines
4.2 KiB
C++

/**********************************************************************
Audacity: A Digital Audio Editor
Profiler.cpp
Created by Michael Chinen (mchinen) on 8/12/08
Audacity(R) is copyright (c) 1999-2008 Audacity Team.
License: GPL v2. See License.txt.
******************************************************************//**
\class Profiler
\brief A simple profiler to measure the average time lengths that a
particular task/function takes. Currently not thread-safe and not thread-smart,
but it will probably work fine if you use it on a high level.
\class TaskProfile
\brief a simple class to keep track of one task that may be called multiple times.
*//*******************************************************************/
#include "Profiler.h"
#include <stdio.h>
#include <string.h>
///write to a profile at the end of the test.
Profiler::~Profiler()
{
if(mTasks.size())
{
//print everything out. append to a log.
FILE* log = fopen("AudacityProfilerLog.txt", "a");
time_t now;
time(&now);
fprintf(log,"Audacity Profiler Run, Ended at ");
fprintf(log,"%s",ctime(&now));
fprintf(log,"****************************************\n");
//print out the tasks
for(int i=0;i<(int)mTasks.size();i++)
{
if(mTasks[i]->mNumHits>0)
{
fprintf(log,"Task: %s\n(begins at line %d in %s)\n\n",mTasks[i]->mDescription,mTasks[i]->mLine,mTasks[i]->mFileName);
fprintf(log,"Number of times run: %d\n",mTasks[i]->mNumHits);
fprintf(log,"Total run time (seconds): %f\n", (double)mTasks[i]->mCumTime/CLOCKS_PER_SEC);
fprintf(log,"Average run time (seconds): %f\n",mTasks[i]->ComputeAverageRunTime());
if(i < ((int)mTasks.size()) -1)
fprintf(log,"----------------------------\n");
}
}
fprintf(log,"\n****************************************\n\n\n");
fclose(log);
//DELETE everything.
for(int i=0;i<(int)mTasks.size();i++)
delete mTasks[i];
}
}
///start the task timer.
void Profiler::Begin(char* fileName, int lineNum, char* taskDescription)
{
mTasksMutex.Lock();
GetOrCreateTaskProfile(fileName,lineNum)->Begin(fileName,lineNum,taskDescription);
mTasksMutex.Unlock();
}
///end the task timer.
void Profiler::End(char* fileName, int lineNum, char* taskDescription)
{
mTasksMutex.Lock();
TaskProfile* tp;
tp=GetTaskProfileByDescription(taskDescription);
if(tp)
tp->End(fileName,lineNum,taskDescription);
mTasksMutex.Unlock();
}
///Gets the singleton instance
Profiler* Profiler::Instance()
{
static Profiler* pro=NULL;
//this isn't 100% threadsafe but I think Okay for this purpose.
if(!pro)
pro = new Profiler();
return pro;
}
///find a taskProfile for the given task, otherwise create
TaskProfile* Profiler::GetOrCreateTaskProfile(char* fileName, int lineNum)
{
for(int i=0;i<(int)mTasks.size();i++)
{
if(strcmp(fileName,mTasks[i]->mFileName)==0 && lineNum == mTasks[i]->mLine)
return mTasks[i];
}
TaskProfile* tp = new TaskProfile();
mTasks.push_back(tp);
return tp;
}
TaskProfile* Profiler::GetTaskProfileByDescription(char* description)
{
for(int i=0;i<(int)mTasks.size();i++)
{
if(strcmp(description,mTasks[i]->mDescription)==0)
return mTasks[i];
}
return NULL;
}
///Task Profile
TaskProfile::TaskProfile()
{
mFileName = NULL;
mCumTime=0;
mNumHits=0;
}
TaskProfile::~TaskProfile()
{
if(mFileName)
{
delete [] mFileName;
delete [] mDescription;
}
}
///start the task timer.
void TaskProfile::Begin(char* fileName, int lineNum, char* taskDescription)
{
if(!mFileName)
{
mFileName = new char[strlen(fileName)+1];
strcpy(mFileName,fileName);
mDescription = new char[strlen(taskDescription)+1];
strcpy(mDescription,taskDescription);
mLine = lineNum;
}
mLastTime = clock();
}
///end the task timer.
void TaskProfile::End(char* WXUNUSED(fileName), int WXUNUSED(lineNum), char* WXUNUSED(taskDescription))
{
mCumTime += clock() - mLastTime;
mNumHits++;
}
double TaskProfile::ComputeAverageRunTime()
{
if(mNumHits)
return (double) ((double)mCumTime/CLOCKS_PER_SEC)/mNumHits;
else
return 0.0;
}