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.
4
5#include "stdafx.h"
6#include "jitperf.h"
7#include "perflog.h"
8#include "clrhost.h"
9#include "contract.h"
10#include "utilcode.h"
11#include "sstring.h"
12
13//=============================================================================
14// ALL THE JIT PERF STATS GATHERING CODE IS COMPILED ONLY IF THE ENABLE_JIT_PERF WAS DEFINED.
15#if defined(ENABLE_JIT_PERF)
16
17__int64 g_JitCycles = 0;
18size_t g_NonJitCycles = 0;
19CRITSEC_COOKIE g_csJit;
20__int64 g_tlsJitCycles = 0;
21int g_fJitPerfOn;
22
23size_t g_dwTlsx86CodeSize = 0;
24size_t g_TotalILCodeSize = 0;
25size_t g_Totalx86CodeSize = 0;
26size_t g_TotalMethodsJitted = 0;
27
28void OutputStats ()
29{
30 CONTRACTL {
31 NOTHROW;
32 GC_NOTRIGGER;
33 CANNOT_TAKE_LOCK;
34 } CONTRACTL_END;
35
36 LARGE_INTEGER cycleFreq;
37 if (QueryPerformanceFrequency (&cycleFreq))
38 {
39 double dJitC = (double) g_JitCycles;
40 double dNonJitC = (double) g_NonJitCycles;
41 double dFreq = (double)cycleFreq.QuadPart;
42 double compileSpeed = (double)g_TotalILCodeSize/(dJitC/dFreq);
43
44 PERFLOG((W("Jit Cycles"), (dJitC - dNonJitC), CYCLES));
45 PERFLOG((W("Jit Time"), (dJitC - dNonJitC)/dFreq, SECONDS));
46 PERFLOG((W("Non Jit Cycles"), dNonJitC, CYCLES));
47 PERFLOG((W("Non Jit Time"), dNonJitC/dFreq, SECONDS));
48 PERFLOG((W("Total Jit Cycles"), dJitC, CYCLES));
49 PERFLOG((W("Total Jit Time"), dJitC/dFreq, SECONDS));
50 PERFLOG((W("Methods Jitted"), (UINT_PTR)g_TotalMethodsJitted, COUNT));
51 PERFLOG((W("IL Code Compiled"), (UINT_PTR)g_TotalILCodeSize, BYTES));
52 PERFLOG((W("X86 Code Emitted"), (UINT_PTR)g_Totalx86CodeSize, BYTES));
53 // Included the perf counter description in this case because its not obvious what we are reporting.
54 PERFLOG((W("ExecTime"), compileSpeed/1000, KBYTES_PER_SEC, W("IL Code compiled/sec")));
55 }
56}
57
58void InitJitPerf(void)
59{
60 CONTRACTL {
61 NOTHROW;
62 GC_NOTRIGGER;
63 CANNOT_TAKE_LOCK;
64 } CONTRACTL_END;
65
66 InlineSString<4> lpszValue;
67 g_fJitPerfOn = WszGetEnvironmentVariable (W("JIT_PERF_OUTPUT"), lpszValue);
68 if (g_fJitPerfOn)
69 {
70 g_csJit = ClrCreateCriticalSection(CrstJitPerf,CRST_UNSAFE_ANYMODE);
71 }
72}
73
74void DoneJitPerfStats()
75{
76 CONTRACTL {
77 NOTHROW;
78 GC_NOTRIGGER;
79 CANNOT_TAKE_LOCK;
80 } CONTRACTL_END;
81
82 if (g_fJitPerfOn)
83 {
84 ClrDeleteCriticalSection(g_csJit);
85
86 // Output stats to stdout and if necessary to the perf automation file.
87 OutputStats();
88 }
89
90
91}
92
93void StartNonJITPerfWorker(LARGE_INTEGER * pCycleStart)
94{
95 CONTRACTL {
96 NOTHROW;
97 GC_NOTRIGGER;
98 CANNOT_TAKE_LOCK;
99 } CONTRACTL_END;
100
101 pCycleStart->QuadPart = 0;
102
103 size_t pTlsNonJitCycles = (size_t) ClrFlsGetValue (TlsIdx_JitPerf);
104 if ((pTlsNonJitCycles & 1) == 0 ) { /* odd value indicates we are in the EE */
105 ClrFlsSetValue(TlsIdx_JitPerf, (LPVOID)(pTlsNonJitCycles + 1));
106 QueryPerformanceCounter(pCycleStart);
107 }
108}
109
110void StopNonJITPerfWorker(LARGE_INTEGER * pCycleStart)
111{
112 CONTRACTL {
113 NOTHROW;
114 GC_NOTRIGGER;
115 CANNOT_TAKE_LOCK;
116 } CONTRACTL_END;
117
118 LARGE_INTEGER CycleStop;
119
120 if (pCycleStart->QuadPart != 0 && QueryPerformanceCounter(&CycleStop) ) {
121 size_t pTlsNonJitCycles = (size_t)ClrFlsGetValue (TlsIdx_JitPerf);
122 pTlsNonJitCycles += static_cast<size_t>(CycleStop.QuadPart - pCycleStart->QuadPart);
123 pTlsNonJitCycles &= ~1; /* even indicate we are not in EE */
124 ClrFlsSetValue(TlsIdx_JitPerf, (LPVOID)(pTlsNonJitCycles));
125 }
126}
127
128
129#endif //ENABLE_JIT_PERF
130
131
132