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/*
6
7 */
8
9
10#include "common.h"
11
12namespace
13{
14// some helper functions
15//
16
17template < typename T >
18void init_array( T * arr, size_t size )
19{
20 ::ZeroMemory( arr, size * sizeof( T ) );
21}
22
23
24// locals
25//
26
27const char * const fixupNames[] =
28{
29 "Class Handle",
30 "Field Handle",
31 "Method Handle",
32 "Function Call/Pointer",
33 "Sync",
34 "Pinvoke",
35 "Profiling Handle",
36 "Interface Table",
37 "Module Handle",
38 "Module Domain ID",
39 "Class Domain ID",
40 "Field Address",
41 "Varargs Handle",
42 "String",
43 "Init Class",
44 "Load Class",
45 "Stub Dispatch",
46 "Active Dependency"
47};
48
49const char * const callReasons[] =
50{
51 "Unknown",
52 "Exotic (Not IL or ECall)",
53 "PInvoke",
54 "Has Generic Instantiation",
55 "No code generated yet",
56 "Method has fixups",
57 "Prestub may produce stub",
58 "Remoting interception",
59 "Contains Cer root",
60 "Restore method (Generics)",
61 "Restore first call",
62 "Restore value type",
63 "Restore",
64 "Can't patch",
65 "Profiling",
66 "Other loader module",
67};
68
69static_assert_no_msg((sizeof(callReasons)/sizeof(callReasons[0])) == CORINFO_INDIRECT_CALL_COUNT);
70
71}
72
73ZapperStats::ZapperStats()
74 : m_methods( 0 )
75 , m_failedMethods( 0 )
76 , m_failedILStubs( 0 )
77 , m_ilCodeSize( 0 )
78 , m_nativeCodeSize( 0 )
79 , m_nativeColdCodeSize( 0 )
80 , m_nativeRODataSize( 0 )
81 , m_gcInfoSize( 0 )
82#ifdef WIN64EXCEPTIONS
83 , m_unwindInfoSize( 0 )
84#endif // WIN64EXCEPTIONS
85 , m_NumHotAllocations( 0 )
86 , m_NumHotColdAllocations( 0 )
87 , m_NumMediumHeaders( 0 )
88 , m_nativeCodeSizeInSplitMethods( 0 )
89 , m_nativeColdCodeSizeInSplitMethods( 0 )
90 , m_nativeCodeSizeInSplitProfiledMethods( 0 )
91 , m_nativeColdCodeSizeInSplitProfiledMethods( 0 )
92 , m_nativeCodeSizeInProfiledMethods( 0 )
93 , m_nativeColdCodeSizeInProfiledMethods( 0 )
94 , m_totalHotCodeSize( 0 )
95 , m_totalUnprofiledCodeSize( 0 )
96 , m_totalColdCodeSize( 0 )
97 , m_totalCodeSizeInProfiledMethods( 0 )
98 , m_totalColdCodeSizeInProfiledMethods( 0 )
99 , m_inputFileSize( 0 )
100 , m_outputFileSize( 0 )
101 , m_metadataSize( 0 )
102 , m_preloadImageSize( 0 )
103 , m_hotCodeMgrSize( 0 )
104 , m_unprofiledCodeMgrSize( 0 )
105 , m_coldCodeMgrSize( 0 )
106 , m_eeInfoTableSize( 0 )
107 , m_helperTableSize( 0 )
108 , m_dynamicInfoTableSize( 0 )
109 , m_dynamicInfoDelayListSize( 0 )
110 , m_debuggingTableSize( 0 )
111 , m_headerSectionSize( 0 )
112 , m_codeSectionSize( 0 )
113 , m_coldCodeSectionSize( 0 )
114 , m_exceptionSectionSize( 0 )
115 , m_readOnlyDataSectionSize( 0 )
116 , m_relocSectionSize( 0 )
117 , m_ILMetadataSize( 0 )
118 , m_externalMethodThunkSize( 0 )
119 , m_externalMethodDataSize( 0 )
120 , m_prestubMethods( 0 )
121 , m_directMethods( 0 )
122{
123 init_array( m_indirectMethodReasons, CORINFO_INDIRECT_CALL_COUNT );
124}
125
126#ifdef _PREFAST_
127#pragma warning(push)
128#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
129#endif
130void ZapperStats::PrintStats()
131{
132 if (m_outputFileSize > 0) {
133
134 GetSvcLogger()->Printf( "-------------------------------------------------------\n");
135 GetSvcLogger()->Printf( "Input file size: %8d\n", m_inputFileSize);
136 GetSvcLogger()->Printf( "Output file size: %8d\n", m_outputFileSize);
137 GetSvcLogger()->Printf( "Input file size/Output file size ratio:\t%8.2fx\n", double( m_outputFileSize ) / m_inputFileSize);
138 GetSvcLogger()->Printf( "\n");
139 GetSvcLogger()->Printf( "Metadata: %8d\t%8.2f%%\n", m_metadataSize, (double)m_metadataSize/m_outputFileSize*100);
140 GetSvcLogger()->Printf( "Debugging maps: %8d\t%8.2f%%\n", m_debuggingTableSize, (double)m_debuggingTableSize/m_outputFileSize*100);
141 GetSvcLogger()->Printf( "Hot Code manager: %8d\t%8.2f%%\n", m_hotCodeMgrSize, (double)m_hotCodeMgrSize/m_outputFileSize*100);
142 GetSvcLogger()->Printf( "Unprofiled Code manager: %8d\t%8.2f%%\n", m_unprofiledCodeMgrSize, (double)m_unprofiledCodeMgrSize/m_outputFileSize*100);
143 GetSvcLogger()->Printf( "Cold Code manager: %8d\t%8.2f%%\n", m_coldCodeMgrSize, (double)m_coldCodeMgrSize/m_outputFileSize*100);
144 GetSvcLogger()->Printf( "GC info: %8d\t%8.2f%%\n", m_headerSectionSize, (double)m_headerSectionSize/m_outputFileSize*100);
145 GetSvcLogger()->Printf( "Native code & r/o data: %8d\t%8.2f%%\n", m_codeSectionSize, (double)m_codeSectionSize/m_outputFileSize*100);
146 GetSvcLogger()->Printf( "Cold code: %8d\t%8.2f%%\n", m_coldCodeSectionSize, (double)m_coldCodeSectionSize/m_outputFileSize*100);
147 GetSvcLogger()->Printf( "Exception tables: %8d\t%8.2f%%\n", m_exceptionSectionSize, (double)m_exceptionSectionSize/m_outputFileSize*100);
148 GetSvcLogger()->Printf( "Relocs: %8d\t%8.2f%%\n", m_relocSectionSize, (double)m_relocSectionSize/m_outputFileSize*100);
149 GetSvcLogger()->Printf( "IL metadata: %8d\t%8.2f%%\n", m_ILMetadataSize, (double)m_ILMetadataSize/m_outputFileSize*100);
150 GetSvcLogger()->Printf( "External Method Thunks: %8d\t%8.2f%%\n", m_externalMethodThunkSize, (double)m_externalMethodThunkSize/m_outputFileSize*100);
151 GetSvcLogger()->Printf( "External Method Data: %8d\t%8.2f%%\n", m_externalMethodDataSize, (double)m_externalMethodDataSize/m_outputFileSize*100);
152 GetSvcLogger()->Printf( "Image of EE structures: %8d\t%8.2f%%\n", m_preloadImageSize, (double)m_preloadImageSize/m_outputFileSize*100);
153
154 unsigned totalIndirections =
155 m_dynamicInfoDelayListSize +
156 m_eeInfoTableSize +
157 m_helperTableSize +
158 m_dynamicInfoTableSize;
159
160 GetSvcLogger()->Printf( "Indirections: %8d\t%8.2f%%\n",
161 totalIndirections, (double)totalIndirections/m_outputFileSize*100);
162 GetSvcLogger()->Printf( " ----- Breakdown of Indirections ----\n");
163
164 GetSvcLogger()->Printf( " Delay load lists: %8d\t%8.2f%%\n",
165 m_dynamicInfoDelayListSize, (double)m_dynamicInfoDelayListSize/totalIndirections*100);
166 GetSvcLogger()->Printf( " Tables: %8d\t%8.2f%%\n",
167 m_dynamicInfoTableSize, (double)m_dynamicInfoTableSize/totalIndirections*100);
168 GetSvcLogger()->Printf( " EE Values: %8d\t%8.2f%%\n",
169 m_eeInfoTableSize, (double)m_eeInfoTableSize/totalIndirections*100);
170 GetSvcLogger()->Printf( " Helper functions: %8d\t%8.2f%%\n",
171 m_helperTableSize, (double)m_helperTableSize/totalIndirections*100);
172 }
173
174 GetSvcLogger()->Printf( " Direct method descs:\t%5d/%5d %8.2f%%\n",
175 m_directMethods, m_prestubMethods+m_directMethods,
176 (double)m_directMethods/(m_directMethods+m_prestubMethods)*100);
177 GetSvcLogger()->Printf( " Indirect method descs:\t%5d/%5d %8.2f%%\n",
178 m_prestubMethods, m_prestubMethods+m_directMethods,
179 (double)m_prestubMethods/(m_directMethods+m_prestubMethods)*100);
180
181 for (int i=0; i < CORINFO_INDIRECT_CALL_COUNT; i++)
182 GetSvcLogger()->Printf( " %-30s %5d %8.2f%%\n",
183 callReasons[i],
184 m_indirectMethodReasons[i],
185 double(m_indirectMethodReasons[i])/(m_directMethods+m_prestubMethods)*100);
186
187 GetSvcLogger()->Printf( "-------------------------------------------------------\n");
188 GetSvcLogger()->Printf( "Total Methods: \t\t\t\t%8d\n", m_methods);
189 GetSvcLogger()->Printf( "Total Hot Only: \t\t\t%8d\n", m_NumHotAllocations);
190 GetSvcLogger()->Printf( "Total Split (Hot/Cold): \t\t%8d\n", m_NumHotColdAllocations);
191 GetSvcLogger()->Printf( "Total Medium Headers: \t\t\t%8d\n", m_NumMediumHeaders);
192 GetSvcLogger()->Printf( "Split Methods: Hot Code \t\t%8d\n", m_nativeCodeSizeInSplitMethods);
193 GetSvcLogger()->Printf( "Split Methods: Cold Code \t\t%8d\n", m_nativeColdCodeSizeInSplitMethods);
194 GetSvcLogger()->Printf( "Split Profiled Methods: Hot Code \t%8d\n", m_nativeCodeSizeInSplitProfiledMethods);
195 GetSvcLogger()->Printf( "Split Profiled Methods: Cold Code \t%8d\n", m_nativeColdCodeSizeInSplitProfiledMethods);
196 GetSvcLogger()->Printf( "Profiled Methods: Hot Code \t\t%8d\n", m_nativeCodeSizeInProfiledMethods);
197 GetSvcLogger()->Printf( "Profiled Methods: Cold Code \t\t%8d\n", m_nativeColdCodeSizeInProfiledMethods);
198 GetSvcLogger()->Printf( "Profiled Methods: Total Hot Code+Headers %7d\n", m_totalCodeSizeInProfiledMethods);
199 GetSvcLogger()->Printf( "Profiled Methods: Total Cold Code+Headers %6d\n", m_totalColdCodeSizeInProfiledMethods);
200 GetSvcLogger()->Printf( "All Methods: Total Hot+Unprofiled Code \t\t%8d\n", m_nativeCodeSize);
201 GetSvcLogger()->Printf( "All Methods: Total Cold Code \t\t%8d\n", m_nativeColdCodeSize);
202 GetSvcLogger()->Printf( "All Methods: Total Hot Code+Headers \t%8d\n", m_totalHotCodeSize);
203 GetSvcLogger()->Printf( "All Methods: Total Unprofiled Code+Headers \t%8d\n", m_totalUnprofiledCodeSize);
204 GetSvcLogger()->Printf( "All Methods: Total Cold Code+Headers \t%8d\n", m_totalColdCodeSize);
205
206 GetSvcLogger()->Printf( "-------------------------------------------------------\n");
207 GetSvcLogger()->Printf( "Total IL Code: %8d\n", m_ilCodeSize);
208 GetSvcLogger()->Printf( "Total Native Code: %8d\n", m_nativeCodeSize + m_nativeColdCodeSize);
209 GetSvcLogger()->Printf( "Total Code+Headers: %8d\n", m_totalHotCodeSize + m_totalUnprofiledCodeSize + m_totalColdCodeSize);
210
211 GetSvcLogger()->Printf( "Total Native RO Data: %8d\n", m_nativeRODataSize);
212 GetSvcLogger()->Printf( "Total Native GC Info: %8d\n", m_gcInfoSize);
213 size_t nativeTotal = m_nativeCodeSize + m_nativeRODataSize + m_gcInfoSize;
214#ifdef WIN64EXCEPTIONS
215 GetSvcLogger()->Printf( "Total Native UnwindInfo:%8d\n", m_unwindInfoSize);
216 nativeTotal += m_unwindInfoSize;
217#endif // WIN64EXCEPTIONS
218 GetSvcLogger()->Printf( "Total Native Total : %8d\n", nativeTotal);
219
220 if (m_methods > 0) {
221 GetSvcLogger()->Printf( "\n");
222 GetSvcLogger()->Printf( "Average IL Code: %8.2f\n", double(m_ilCodeSize) / m_methods);
223 GetSvcLogger()->Printf( "Average NativeCode: %8.2f\n", double(m_nativeCodeSize) / m_methods);
224 GetSvcLogger()->Printf( "Average Native RO Data: %8.2f\n", double(m_nativeRODataSize) / m_methods);
225 GetSvcLogger()->Printf( "Average Native GC Info: %8.2f\n", double(m_gcInfoSize) / m_methods);
226#ifdef WIN64EXCEPTIONS
227 GetSvcLogger()->Printf( "Average Native UnwindInfo: %8.2f\n", double(m_unwindInfoSize) / m_methods);
228#endif // WIN64EXCEPTIONS
229 GetSvcLogger()->Printf( "Average Native: %8.2f\n", double(nativeTotal) / m_methods);
230 GetSvcLogger()->Printf( "\n");
231 GetSvcLogger()->Printf( "NativeGC / Native: %8.2f\n", double(m_gcInfoSize) / nativeTotal);
232 GetSvcLogger()->Printf( "Native / IL: %8.2f\n", double(nativeTotal) / m_ilCodeSize);
233 }
234
235 if (m_failedMethods > 0)
236 GetSvcLogger()->Printf( "Methods which did not compile: %d\n", m_failedMethods);
237 if (m_failedILStubs > 0)
238 GetSvcLogger()->Printf( "IL STUBS which did not compile: %d\n", m_failedILStubs);
239}
240#ifdef _PREFAST_
241#pragma warning(pop)
242#endif
243
244char const * GetCallReasonString( CorInfoIndirectCallReason reason )
245{
246 return callReasons[ reason ];
247}
248