OSDN Git Service

Add Show Whole Project Button at commitDialog
[tortoisegit/TortoiseGitJp.git] / src / Utils / ProfilingInfo.h
1 #pragma once\r
2 \r
3 // TortoiseSVN - a Windows shell extension for easy version control\r
4 \r
5 // Copyright (C) 2003-2008 - TortoiseSVN\r
6 \r
7 // This program is free software; you can redistribute it and/or\r
8 // modify it under the terms of the GNU General Public License\r
9 // as published by the Free Software Foundation; either version 2\r
10 // of the License, or (at your option) any later version.\r
11 \r
12 // This program is distributed in the hope that it will be useful,\r
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15 // GNU General Public License for more details.\r
16 \r
17 // You should have received a copy of the GNU General Public License\r
18 // along with this program; if not, write to the Free Software Foundation,\r
19 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
20 //\r
21 \r
22 //////////////////////////////////////////////////////////////////////\r
23 // required includes\r
24 //////////////////////////////////////////////////////////////////////\r
25 \r
26 #ifndef _DEBUG\r
27 #ifndef __INTRIN_H_\r
28 #include <intrin.h>\r
29 #endif\r
30 #endif\r
31 \r
32 #ifndef _PSAPI_H_\r
33 #include <psapi.h>\r
34 #endif\r
35 \r
36 #ifndef _STRING_\r
37 #include <string>\r
38 #endif\r
39 \r
40 #ifndef _VECTOR_\r
41 #include <vector>\r
42 #endif\r
43 \r
44 #pragma comment (lib, "psapi.lib")\r
45 \r
46 /**\r
47 * Collects the profiling info for a given profiled block / line.\r
48 * Records execution count, min, max and accumulated execution time\r
49 * in CPU clock ticks.\r
50 */\r
51 \r
52 class CProfilingRecord\r
53 {\r
54 private:\r
55 \r
56     /// identification\r
57 \r
58     const char* name;\r
59     const char* file;\r
60     int line;\r
61 \r
62     /// collected profiling info\r
63 \r
64     size_t count;\r
65     unsigned __int64 sum;\r
66     unsigned __int64 minValue;\r
67     unsigned __int64 maxValue;\r
68 \r
69 public:\r
70 \r
71     /// construction \r
72 \r
73     CProfilingRecord ( const char* name\r
74                      , const char* file\r
75                      , int line);\r
76 \r
77     /// record values\r
78 \r
79     void Add (unsigned __int64 value);\r
80 \r
81     /// modification\r
82 \r
83     void Reset();\r
84 \r
85     /// data access\r
86 \r
87         const char* GetName() const {return name;}\r
88         const char* GetFile() const {return file;}\r
89         int GetLine() const {return line;}\r
90 \r
91         size_t GetCount() const {return count;}\r
92     unsigned __int64 GetSum() const {return sum;}\r
93         unsigned __int64 GetMinValue() const {return minValue;}\r
94     unsigned __int64 GetMaxValue() const {return maxValue;}\r
95 };\r
96 \r
97 /**\r
98 * RAII class that encapsulates a single execution of a profiled\r
99 * block / line. The result gets added to an existing profiling record.\r
100 */\r
101 \r
102 class CRecordProfileEvent\r
103 {\r
104 private:\r
105 \r
106     CProfilingRecord* record;\r
107 \r
108         /// the initial CPU counter value\r
109 \r
110     unsigned __int64 start;\r
111 \r
112 public:\r
113 \r
114     /// construction: start clock\r
115 \r
116     CRecordProfileEvent (CProfilingRecord* aRecord);\r
117 \r
118         /// destruction: time interval to profiling record, \r
119         /// if Stop() had not been called before\r
120 \r
121         ~CRecordProfileEvent();\r
122 \r
123         /// don't wait for destruction\r
124 \r
125         void Stop();\r
126 };\r
127 \r
128 #ifndef _DEBUG\r
129 \r
130 /// construction / destruction\r
131 \r
132 inline CRecordProfileEvent::CRecordProfileEvent (CProfilingRecord* aRecord)\r
133     : record (aRecord)\r
134     , start (__rdtsc())\r
135 {\r
136 }\r
137 \r
138 inline CRecordProfileEvent::~CRecordProfileEvent()\r
139 {\r
140         if (record)\r
141                 record->Add (__rdtsc() - start);\r
142 }\r
143 \r
144 #endif\r
145 \r
146 /// don't wait for destruction\r
147 \r
148 inline void CRecordProfileEvent::Stop()\r
149 {\r
150         if (record)\r
151         {\r
152                 record->Add (__rdtsc() - start);\r
153                 record = NULL;\r
154         }\r
155 }\r
156 \r
157 /**\r
158 * Singleton class that acts as container for all profiling records.\r
159 * You may reset its content as well as write it to disk.\r
160 */\r
161 \r
162 class CProfilingInfo\r
163 {\r
164 private:\r
165 \r
166     typedef std::vector<CProfilingRecord*> TRecords;\r
167     TRecords records;\r
168 \r
169     /// construction / destruction\r
170 \r
171     CProfilingInfo();\r
172     ~CProfilingInfo(void);\r
173 \r
174         /// create report\r
175 \r
176         std::string GetReport() const;\r
177 \r
178 public:\r
179 \r
180     /// access to default instance\r
181 \r
182     static CProfilingInfo* GetInstance();\r
183 \r
184     /// add a new record\r
185 \r
186     CProfilingRecord* Create ( const char* name\r
187                              , const char* file\r
188                              , int line);\r
189 };\r
190 \r
191 /**\r
192 * Profiling macros\r
193 */\r
194 \r
195 #define PROFILE_CONCAT3( a, b )  a##b\r
196 #define PROFILE_CONCAT2( a, b )  PROFILE_CONCAT3( a, b )\r
197 #define PROFILE_CONCAT( a, b )   PROFILE_CONCAT2( a, b )\r
198 \r
199 /// measures the time from the point of usage to the end of the respective block\r
200 \r
201 #define PROFILE_BLOCK\\r
202     static CProfilingRecord* PROFILE_CONCAT(record,__LINE__) \\r
203         = CProfilingInfo::GetInstance()->Create(__FUNCTION__,__FILE__,__LINE__);\\r
204     CRecordProfileEvent PROFILE_CONCAT(profileSection,__LINE__) (PROFILE_CONCAT(record,__LINE__));\r
205 \r
206 /// measures the time taken to execute the respective code line\r
207 \r
208 #define PROFILE_LINE(line)\\r
209     static CProfilingRecord* PROFILE_CONCAT(record,__LINE__) \\r
210         = CProfilingInfo::GetInstance()->Create(__FUNCTION__,__FILE__,__LINE__);\\r
211     CRecordProfileEvent PROFILE_CONCAT(profileSection,__LINE__) (PROFILE_CONCAT(record,__LINE__));\\r
212     line;\\r
213     PROFILE_CONCAT(profileSection,__LINE__).Stop();\r
214 \r