1 /**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 Profiler.cpp
6
7 Created by Michael Chinen (mchinen) on 8/12/08
8 Audacity(R) is copyright (c) 1999-2008 Audacity Team.
9 License: GPL v2. See License.txt.
10
11 ******************************************************************//**
12
13 \class Profiler
14 \brief A simple profiler to measure the average time lengths that a
15 particular task/function takes. Currently not thread-safe and not thread-smart,
16 but it will probably work fine if you use it on a high level.
17
18 \class TaskProfile
19 \brief a simple class to keep track of one task that may be called multiple times.
20
21 *//*******************************************************************/
22
23
24 #include "Profiler.h"
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <wx/crt.h>
29
30 ///write to a profile at the end of the test.
~Profiler()31 Profiler::~Profiler()
32 {
33 if(mTasks.size())
34 {
35 //print everything out. append to a log.
36 FILE* log = fopen("AudacityProfilerLog.txt", "a");
37 time_t now;
38
39 time(&now);
40 wxFprintf(log,"Audacity Profiler Run, Ended at ");
41 wxFprintf(log,"%s",ctime(&now));
42 wxFprintf(log,"****************************************\n");
43 //print out the tasks
44 for(int i=0;i<(int)mTasks.size();i++)
45 {
46 if(mTasks[i]->mNumHits>0)
47 {
48 wxFprintf(log,"Task: %s\n(begins at line %d in %s)\n\n",mTasks[i]->mDescription.get(), mTasks[i]->mLine, mTasks[i]->mFileName.get());
49 wxFprintf(log,"Number of times run: %d\n",mTasks[i]->mNumHits);
50 wxFprintf(log,"Total run time (seconds): %f\n", (double)mTasks[i]->mCumTime/CLOCKS_PER_SEC);
51 wxFprintf(log,"Average run time (seconds): %f\n",mTasks[i]->ComputeAverageRunTime());
52
53 if(i < ((int)mTasks.size()) -1)
54 wxFprintf(log,"----------------------------\n");
55 }
56 }
57 wxFprintf(log,"\n****************************************\n\n\n");
58
59 fclose(log);
60 }
61 }
62
63 ///start the task timer.
Begin(const char * fileName,int lineNum,const char * taskDescription)64 void Profiler::Begin(const char* fileName, int lineNum, const char* taskDescription)
65 {
66 std::lock_guard<std::mutex> guard{ mTasksMutex };
67 GetOrCreateTaskProfile(fileName,lineNum)->Begin(fileName,lineNum,taskDescription);
68 }
69
70 ///end the task timer.
End(const char * fileName,int lineNum,const char * taskDescription)71 void Profiler::End(const char* fileName, int lineNum, const char* taskDescription)
72 {
73 std::lock_guard<std::mutex> guard{ mTasksMutex };
74 TaskProfile* tp;
75 tp=GetTaskProfileByDescription(taskDescription);
76 if(tp)
77 tp->End(fileName,lineNum,taskDescription);
78 }
79
80 ///Gets the singleton instance
Instance()81 Profiler* Profiler::Instance()
82 {
83 static Profiler pro;
84 //this isn't 100% threadsafe but I think Okay for this purpose.
85
86 return &pro;
87 }
88
89 ///find a taskProfile for the given task, otherwise create
GetOrCreateTaskProfile(const char * fileName,int lineNum)90 TaskProfile* Profiler::GetOrCreateTaskProfile(const char* fileName, int lineNum)
91 {
92 for(int i=0;i<(int)mTasks.size();i++)
93 {
94 if(strcmp(fileName, mTasks[i]->mFileName.get())==0 && lineNum == mTasks[i]->mLine)
95 return mTasks[i].get();
96 }
97
98 auto tp = std::make_unique<TaskProfile>();
99 mTasks.push_back(std::move(tp));
100 return mTasks.back().get();
101 }
102
GetTaskProfileByDescription(const char * description)103 TaskProfile* Profiler::GetTaskProfileByDescription(const char* description)
104 {
105 for(int i=0;i<(int)mTasks.size();i++)
106 {
107 if(strcmp(description, mTasks[i]->mDescription.get())==0)
108 return mTasks[i].get();
109 }
110
111 return NULL;
112
113 }
114
115
116 ///Task Profile
TaskProfile()117 TaskProfile::TaskProfile()
118 {
119 mCumTime=0;
120 mNumHits=0;
121 }
122
~TaskProfile()123 TaskProfile::~TaskProfile()
124 {
125 }
126
127 ///start the task timer.
Begin(const char * fileName,int lineNum,const char * taskDescription)128 void TaskProfile::Begin(const char* fileName, int lineNum, const char* taskDescription)
129 {
130 if(!mFileName)
131 {
132 mFileName.reinit( strlen(fileName) + 1 );
133 strcpy(mFileName.get(), fileName);
134 mDescription.reinit( strlen(taskDescription) + 1 );
135 strcpy(mDescription.get(), taskDescription);
136 mLine = lineNum;
137 }
138
139 mLastTime = clock();
140
141 }
142
143 ///end the task timer.
End(const char * WXUNUSED (fileName),int WXUNUSED (lineNum),const char * WXUNUSED (taskDescription))144 void TaskProfile::End(const char* WXUNUSED(fileName), int WXUNUSED(lineNum), const char* WXUNUSED(taskDescription))
145 {
146 mCumTime += clock() - mLastTime;
147 mNumHits++;
148 }
149
ComputeAverageRunTime()150 double TaskProfile::ComputeAverageRunTime()
151 {
152 if(mNumHits)
153 return (double) ((double)mCumTime/CLOCKS_PER_SEC)/mNumHits;
154 else
155 return 0.0;
156 }
157