OSDN Git Service

Fix create socket error and add retry when send fail.
[tortoisegit/TortoiseGitJp.git] / src / Utils / ProfilingInfo.cpp
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2003-2008 - TortoiseSVN\r
4 \r
5 // This program is free software; you can redistribute it and/or\r
6 // modify it under the terms of the GNU General Public License\r
7 // as published by the Free Software Foundation; either version 2\r
8 // of the License, or (at your option) any later version.\r
9 \r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 \r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, write to the Free Software Foundation,\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
18 //\r
19 \r
20 #include "stdafx.h"\r
21 \r
22 #ifndef __INTRIN_H_\r
23 #include <intrin.h>\r
24 #endif\r
25 \r
26 #include "ProfilingInfo.h"\r
27 \r
28 #ifdef _DEBUG\r
29 \r
30 //////////////////////////////////////////////////////////////////////\r
31 /// construction / destruction\r
32 //////////////////////////////////////////////////////////////////////\r
33 \r
34 CRecordProfileEvent::CRecordProfileEvent (CProfilingRecord* aRecord)\r
35     : record (aRecord)\r
36     , start (__rdtsc())\r
37 {\r
38 }\r
39 \r
40 CRecordProfileEvent::~CRecordProfileEvent()\r
41 {\r
42         if (record)\r
43                 record->Add (__rdtsc() - start);\r
44 }\r
45 \r
46 #endif\r
47 \r
48 //////////////////////////////////////////////////////////////////////\r
49 // construction / destruction\r
50 //////////////////////////////////////////////////////////////////////\r
51 \r
52 CProfilingRecord::CProfilingRecord ( const char* name\r
53                                    , const char* file\r
54                                    , int line)\r
55     : name (name)\r
56     , file (file)\r
57     , line (line)\r
58     , count (0)\r
59     , sum (0)\r
60     , minValue (ULLONG_MAX)\r
61     , maxValue (0)\r
62 {\r
63 }\r
64 \r
65 //////////////////////////////////////////////////////////////////////\r
66 // record values\r
67 //////////////////////////////////////////////////////////////////////\r
68 \r
69 void CProfilingRecord::Add (unsigned __int64 value)\r
70 {\r
71     ++count;\r
72     sum += value;\r
73 \r
74     if (value < minValue)\r
75         minValue = value;\r
76     if (value > maxValue)\r
77         maxValue = value;\r
78 }\r
79 \r
80 //////////////////////////////////////////////////////////////////////\r
81 // modification\r
82 //////////////////////////////////////////////////////////////////////\r
83 \r
84 void CProfilingRecord::Reset()\r
85 {\r
86     count = 0;\r
87     sum = 0;\r
88 \r
89     minValue = LLONG_MAX;\r
90     maxValue = 0;\r
91 }\r
92 \r
93 //////////////////////////////////////////////////////////////////////\r
94 // construction / destruction\r
95 //////////////////////////////////////////////////////////////////////\r
96 \r
97 CProfilingInfo::CProfilingInfo()\r
98 {\r
99 }\r
100 \r
101 CProfilingInfo::~CProfilingInfo(void)\r
102 {\r
103         if (records.size() > 0)\r
104         {\r
105                 // write profile to file\r
106 \r
107                 TCHAR buffer [MAX_PATH];\r
108                 if (GetModuleFileNameEx (GetCurrentProcess(), NULL, buffer, MAX_PATH) > 0)\r
109                         try\r
110                         {\r
111                                 std::wstring fileName (buffer);\r
112                                 fileName += L".profile";\r
113 \r
114                                 std::string report = GetInstance()->GetReport();\r
115 \r
116                                 CFile file (fileName.c_str(), CFile::modeCreate | CFile::modeWrite );\r
117                                 file.Write (report.c_str(), (UINT)report.size());\r
118                         }\r
119                         catch (...)\r
120                         {\r
121                                 // ignore all file errors etc.\r
122                         }\r
123 \r
124 \r
125                 // free data\r
126 \r
127                 for (size_t i = 0; i < records.size(); ++i)\r
128                         delete records[i];\r
129         }\r
130 }\r
131 \r
132 //////////////////////////////////////////////////////////////////////\r
133 // access to default instance\r
134 //////////////////////////////////////////////////////////////////////\r
135 \r
136 CProfilingInfo* CProfilingInfo::GetInstance()\r
137 {\r
138     static CProfilingInfo instance;\r
139     return &instance;\r
140 }\r
141 \r
142 //////////////////////////////////////////////////////////////////////\r
143 // create a report\r
144 //////////////////////////////////////////////////////////////////////\r
145 \r
146 static std::string IntToStr (unsigned __int64 value)\r
147 {\r
148         char buffer[100];\r
149         _ui64toa_s (value, buffer, 100, 10);\r
150 \r
151         std::string result = buffer;\r
152         for (size_t i = 3; i < result.length(); i += 4)\r
153                 result.insert (result.length() - i, 1, ',');\r
154 \r
155         return result;\r
156 };\r
157 \r
158 std::string CProfilingInfo::GetReport() const\r
159 {\r
160     enum { LINE_LENGTH = 500 };\r
161 \r
162     char lineBuffer [LINE_LENGTH];\r
163     const char * const format ="%10s%17s%17s%17s%6s %s\t%s\n";\r
164 \r
165     std::string result;\r
166     result.reserve (LINE_LENGTH * records.size());\r
167     sprintf_s ( lineBuffer, format\r
168               , "count", "sum", "min", "max"\r
169               , "line", "name", "file");\r
170     result += lineBuffer;\r
171 \r
172     for ( TRecords::const_iterator iter = records.begin(), end = records.end()\r
173         ; iter != end\r
174         ; ++iter)\r
175     {\r
176         unsigned __int64 minValue = (*iter)->GetMinValue();\r
177         if (minValue == ULLONG_MAX)\r
178             minValue = 0;\r
179 \r
180         sprintf_s ( lineBuffer, format\r
181 \r
182                   , IntToStr ((*iter)->GetCount()).c_str()\r
183                   , IntToStr ((*iter)->GetSum()).c_str()\r
184                   , IntToStr (minValue).c_str()\r
185                   , IntToStr ((*iter)->GetMaxValue()).c_str()\r
186 \r
187                   , IntToStr ((*iter)->GetLine()).c_str()\r
188                   , (*iter)->GetName()\r
189                   , (*iter)->GetFile());\r
190 \r
191         result += lineBuffer;\r
192     }\r
193 \r
194     return result;\r
195 }\r
196 \r
197 //////////////////////////////////////////////////////////////////////\r
198 // add a new record\r
199 //////////////////////////////////////////////////////////////////////\r
200 \r
201 CProfilingRecord* CProfilingInfo::Create ( const char* name\r
202                                          , const char* file\r
203                                          , int line)\r
204 {\r
205     CProfilingRecord* record = new CProfilingRecord (name, file, line);\r
206     records.push_back (record);\r
207 \r
208     return record;\r
209 }\r
210 \r