1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
11 //=============================================================================
12 // ALL THE PERF LOG CODE IS COMPILED ONLY IF ENABLE_PERF_LOG IS DEFINED.
13 #if defined (ENABLE_PERF_LOG)
14 //=============================================================================
16 //-----------------------------------------------------------------------------
17 // Widechar strings representing the units in UnitOfMeasure. *** Keep in sync ***
18 // with the array defined in PerfLog.cpp
19 const wchar_t * const wszUnitOfMeasureDescr[MAX_UNITS_OF_MEASURE] =
29 //-----------------------------------------------------------------------------
30 // Widechar strings representing the "direction" property of above units.
31 // *** Keep in sync *** with the array defined in PerfLog.cpp
32 // "Direction" property is false if an increase in the value of the counter indicates
34 // "Direction" property is true if an increase in the value of the counter indicates
36 const wchar_t * const wszIDirection[MAX_UNITS_OF_MEASURE] =
46 //-----------------------------------------------------------------------------
47 // Initialize static variables of the PerfLog class.
48 bool PerfLog::m_perfLogInit = false;
49 wchar_t PerfLog::m_wszOutStr_1[];
50 DWORD PerfLog::m_dwWriteByte = 0;
51 int PerfLog::m_fLogPerfData = 0;
52 HANDLE PerfLog::m_hPerfLogFileHandle = 0;
53 bool PerfLog::m_perfAutomationFormat = false;
54 bool PerfLog::m_commaSeparatedFormat = false;
56 //-----------------------------------------------------------------------------
57 // Initliaze perf logging. Must be called before calling PERFLOG (x)...
58 void PerfLog::PerfLogInitialize()
60 LIMITED_METHOD_CONTRACT;
62 // Make sure we are called only once.
68 // First check for special cases:
70 #if defined(ENABLE_JIT_PERF)
71 // Checks the JIT_PERF_OUTPUT env var and sets g_fJitPerfOn.
76 // Private working set perf stats
80 // Put other special cases here.
82 // <TODO>@TODO agk: clean this logic a bit</TODO>
83 // Special cases considered. Now turn on loggin if any of above want logging
84 // or if PERF_OUTPUT says so.
86 InlineSString<4> lpszValue;
87 // Read the env var PERF_OUTPUT and if set continue.
88 m_fLogPerfData = WszGetEnvironmentVariable (W("PERF_OUTPUT"), lpszValue);
90 #if defined(ENABLE_JIT_PERF)
93 // Make sure that JIT perf was not requested.
97 // JIT perf stats are needed so set the flags also.
102 // See if we want to output to the database
103 PathString _lpszValue;
104 DWORD _cchValue = 10; // 11 - 1
105 _cchValue = WszGetEnvironmentVariable (W("PerfOutput"), _lpszValue);
106 if (_cchValue && (wcscmp (_lpszValue, W("DBase")) == 0))
107 m_perfAutomationFormat = true;
108 if (_cchValue && (wcscmp (_lpszValue, W("CSV")) == 0))
109 m_commaSeparatedFormat = true;
111 if (PerfAutomationFormat() || CommaSeparatedFormat())
113 // Hardcoded file name for spitting the perf auotmation formatted perf data. Open
114 // the file here for writing and close in PerfLogDone().
115 m_hPerfLogFileHandle = WszCreateFile (
117 W("/tmp/PerfData.dat"),
119 W("C:\\PerfData.dat"),
125 FILE_ATTRIBUTE_NORMAL,
128 // check return value
129 if(m_hPerfLogFileHandle == INVALID_HANDLE_VALUE)
135 // Make sure we append to the file. <TODO>@TODO agk: Is this necessary?</TODO>
136 if(SetFilePointer (m_hPerfLogFileHandle, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER )
138 CloseHandle (m_hPerfLogFileHandle);
144 m_perfLogInit = true;
151 void PerfLog::PerfLogDone()
153 LIMITED_METHOD_CONTRACT;
155 #if defined(ENABLE_JIT_PERF)
160 // Private working set perf
164 if (CommaSeparatedFormat())
166 if (0 == WriteFile (m_hPerfLogFileHandle, "\n", (DWORD)strlen("\n"), &m_dwWriteByte, NULL))
167 printf("ERROR: Could not write to perf log.\n");
170 if (PerfLoggingEnabled())
171 CloseHandle (m_hPerfLogFileHandle);
174 void PerfLog::OutToStdout(__in_z const wchar_t *wszName, UnitOfMeasure unit, __in_opt const wchar_t *wszDescr)
176 LIMITED_METHOD_CONTRACT;
178 wchar_t wszOutStr_2[PRINT_STR_LEN];
181 _snwprintf_s(wszOutStr_2, PRINT_STR_LEN, PRINT_STR_LEN - 1, W(" (%s)\n"), wszDescr);
183 _snwprintf_s(wszOutStr_2, PRINT_STR_LEN, PRINT_STR_LEN - 1, W("\n"));
185 printf("%S", m_wszOutStr_1);
186 printf("%S", wszOutStr_2);
189 void PerfLog::OutToPerfFile(__in_z const wchar_t *wszName, UnitOfMeasure unit, __in_opt const wchar_t *wszDescr)
191 LIMITED_METHOD_CONTRACT;
193 char szPrintStr[PRINT_STR_LEN];
195 if (CommaSeparatedFormat())
197 if (WszWideCharToMultiByte (CP_ACP, 0, m_wszOutStr_1, -1, szPrintStr, PRINT_STR_LEN-1, 0, 0) ) {
198 if (0 == WriteFile (m_hPerfLogFileHandle, szPrintStr, (DWORD)strlen(szPrintStr), &m_dwWriteByte, NULL))
199 printf("ERROR: Could not write to perf log.\n");
202 wprintf(W("ERROR: Could not do string conversion.\n"));
206 wchar_t wszOutStr_2[PRINT_STR_LEN];
208 // workaround. The formats for ExecTime is slightly different from a custom value.
209 if (wcscmp(wszName, W("ExecTime")) == 0)
210 _snwprintf_s(wszOutStr_2, PRINT_STR_LEN, PRINT_STR_LEN - 1, W("ExecUnitDescr=%s\nExecIDirection=%s\n"), wszDescr, wszIDirection[unit]);
214 _snwprintf_s(wszOutStr_2, PRINT_STR_LEN, PRINT_STR_LEN - 1, W("%s Descr=%s\n%s Unit Descr=None\n%s IDirection=%s\n"), wszName, wszDescr, wszName, wszName, wszIDirection[unit]);
216 _snwprintf_s(wszOutStr_2, PRINT_STR_LEN, PRINT_STR_LEN - 1, W("%s Descr=None\n%s Unit Descr=None\n%s IDirection=%s\n"), wszName, wszName, wszName, wszIDirection[unit]);
219 // Write both pieces to the file.
220 if(WszWideCharToMultiByte (CP_ACP, 0, m_wszOutStr_1, -1, szPrintStr, PRINT_STR_LEN-1, 0, 0) ) {
221 if (0 == WriteFile (m_hPerfLogFileHandle, szPrintStr, (DWORD)strlen(szPrintStr), &m_dwWriteByte, NULL))
222 printf("ERROR: Could not write to perf log.\n");
225 wprintf(W("ERROR: Could not do string conversion.\n"));
227 if(WszWideCharToMultiByte (CP_ACP, 0, wszOutStr_2, -1, szPrintStr, PRINT_STR_LEN-1, 0, 0)) {
228 if (0 == WriteFile (m_hPerfLogFileHandle, szPrintStr, (DWORD)strlen(szPrintStr), &m_dwWriteByte, NULL))
229 printf("ERROR: Could not write to perf log.\n");
232 wprintf(W("ERROR: Could not do string conversion.\n"));
236 // Output stats in pretty print to stdout and perf automation format to file
237 // handle m_hPerfLogFileHandle
238 void PerfLog::Log(__in_z const wchar_t *wszName, UINT64 val, UnitOfMeasure unit, __in_opt const wchar_t *wszDescr)
240 LIMITED_METHOD_CONTRACT;
242 // Format the output into two pieces: The first piece is formatted here, rest in OutToStdout.
243 _snwprintf_s(m_wszOutStr_1, PRINT_STR_LEN, PRINT_STR_LEN - 1, W("%-30s%12.3I64u %s"), wszName, val, wszUnitOfMeasureDescr[unit]);
244 OutToStdout (wszName, unit, wszDescr);
246 // Format the output into two pieces: The first piece is formatted here, rest in OutToPerfFile
247 if (CommaSeparatedFormat())
249 _snwprintf_s(m_wszOutStr_1, PRINT_STR_LEN, PRINT_STR_LEN - 1, W("%s;%0.3I64u;"), wszName, val);
250 OutToPerfFile (wszName, unit, wszDescr);
253 if (PerfAutomationFormat())
255 // workaround, Special case for ExecTime. since the format is slightly different than for custom value.
256 if (wcscmp(wszName, W("ExecTime")) == 0)
257 _snwprintf_s(m_wszOutStr_1, PRINT_STR_LEN, PRINT_STR_LEN - 1, W("%s=%0.3I64u\nExecUnit=%s\n"), wszName, val, wszUnitOfMeasureDescr[unit]);
259 _snwprintf_s(m_wszOutStr_1, PRINT_STR_LEN, PRINT_STR_LEN - 1, W("%s=%0.3I64u\n%s Unit=%s\n"), wszName, val, wszName, wszUnitOfMeasureDescr[unit]);
260 OutToPerfFile (wszName, unit, wszDescr);
264 // Output stats in pretty print to stdout and perf automation format to file
265 // handle m_hPerfLogFileHandle
266 void PerfLog::Log(__in_z const wchar_t *wszName, double val, UnitOfMeasure unit, __in_opt const wchar_t *wszDescr)
268 LIMITED_METHOD_CONTRACT;
270 // Format the output into two pieces: The first piece is formatted here, rest in OutToStdout.
271 _snwprintf_s(m_wszOutStr_1, PRINT_STR_LEN, PRINT_STR_LEN - 1, W("%-30s%12.3g %s"), wszName, val, wszUnitOfMeasureDescr[unit]);
272 OutToStdout (wszName, unit, wszDescr);
274 // Format the output into two pieces: The first piece is formatted here, rest in OutToPerfFile
275 if (CommaSeparatedFormat())
277 _snwprintf_s(m_wszOutStr_1, PRINT_STR_LEN, PRINT_STR_LEN - 1, W("%s;%0.3g;"), wszName, val);
278 OutToPerfFile (wszName, unit, wszDescr);
281 if (PerfAutomationFormat())
283 // workaround, Special case for ExecTime. since the format is slightly different than for custom value.
284 if (wcscmp(wszName, W("ExecTime")) == 0)
285 _snwprintf_s(m_wszOutStr_1, PRINT_STR_LEN, PRINT_STR_LEN - 1, W("%s=%0.3g\nExecUnit=%s\n"), wszName, val, wszUnitOfMeasureDescr[unit]);
287 _snwprintf_s(m_wszOutStr_1, PRINT_STR_LEN, PRINT_STR_LEN - 1, W("%s=%0.3g\n%s Unit=%s\n"), wszName, val, wszName, wszUnitOfMeasureDescr[unit]);
288 OutToPerfFile (wszName, unit, wszDescr);
292 // Output stats in pretty print to stdout and perf automation format to file
293 // handle m_hPerfLogFileHandle
294 void PerfLog::Log(__in_z const wchar_t *wszName, UINT32 val, UnitOfMeasure unit, __in_opt const wchar_t *wszDescr)
296 LIMITED_METHOD_CONTRACT;
298 // Format the output into two pieces: The first piece is formatted here, rest in OutToStdout.
300 _snwprintf_s(m_wszOutStr_1, PRINT_STR_LEN, PRINT_STR_LEN - 1, W("%-30s%12d %s"), wszName, val, wszUnitOfMeasureDescr[unit]);
301 OutToStdout (wszName, unit, wszDescr);
303 // Format the output into two pieces: The first piece is formatted here, rest in OutToPerfFile
304 if (CommaSeparatedFormat())
306 _snwprintf_s(m_wszOutStr_1, PRINT_STR_LEN, PRINT_STR_LEN - 1, W("%s;%d;"), wszName, val);
307 OutToPerfFile (wszName, unit, wszDescr);
310 if (PerfAutomationFormat())
312 // workaround, Special case for ExecTime. since the format is slightly different than for custom value.
313 if (wcscmp(wszName, W("ExecTime")) == 0)
314 _snwprintf_s(m_wszOutStr_1, PRINT_STR_LEN, PRINT_STR_LEN - 1, W("%s=%0.3d\nExecUnit=%s\n"), wszName, val, wszUnitOfMeasureDescr[unit]);
316 _snwprintf_s(m_wszOutStr_1, PRINT_STR_LEN, PRINT_STR_LEN - 1, W("%s=%0.3d\n%s Unit=%s\n"), wszName, val, wszName, wszUnitOfMeasureDescr[unit]);
317 OutToPerfFile (wszName, unit, wszDescr);
322 //=============================================================================
323 // ALL THE PERF LOG CODE IS COMPILED ONLY IF THE ENABLE_PERF_LOG WAS DEFINED.
324 #endif // ENABLE_PERF_LOG
325 //=============================================================================