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.
14 // some helper functions
17 template < typename T >
18 void init_array( T * arr, size_t size )
20 ::ZeroMemory( arr, size * sizeof( T ) );
27 const char * const fixupNames[] =
32 "Function Call/Pointer",
49 const char * const callReasons[] =
52 "Exotic (Not IL or ECall)",
54 "Has Generic Instantiation",
55 "No code generated yet",
57 "Prestub may produce stub",
58 "Remoting interception",
60 "Restore method (Generics)",
66 "Other loader module",
69 static_assert_no_msg((sizeof(callReasons)/sizeof(callReasons[0])) == CORINFO_INDIRECT_CALL_COUNT);
73 ZapperStats::ZapperStats()
75 , m_failedMethods( 0 )
76 , m_failedILStubs( 0 )
78 , m_nativeCodeSize( 0 )
79 , m_nativeColdCodeSize( 0 )
80 , m_nativeRODataSize( 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_importTableSize( 0 )
111 , m_debuggingTableSize( 0 )
112 , m_headerSectionSize( 0 )
113 , m_codeSectionSize( 0 )
114 , m_coldCodeSectionSize( 0 )
115 , m_exceptionSectionSize( 0 )
116 , m_readOnlyDataSectionSize( 0 )
117 , m_relocSectionSize( 0 )
118 , m_ILMetadataSize( 0 )
119 , m_externalMethodThunkSize( 0 )
120 , m_externalMethodDataSize( 0 )
121 , m_prestubMethods( 0 )
122 , m_directMethods( 0 )
124 init_array( m_indirectMethodReasons, CORINFO_INDIRECT_CALL_COUNT );
128 #pragma warning(push)
129 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
131 void ZapperStats::PrintStats()
133 if (m_outputFileSize > 0) {
135 GetSvcLogger()->Printf( "-------------------------------------------------------\n");
136 GetSvcLogger()->Printf( "Input file size: %8d\n", m_inputFileSize);
137 GetSvcLogger()->Printf( "Output file size: %8d\n", m_outputFileSize);
138 GetSvcLogger()->Printf( "Input file size/Output file size ratio:\t%8.2fx\n", double( m_outputFileSize ) / m_inputFileSize);
139 GetSvcLogger()->Printf( "\n");
140 GetSvcLogger()->Printf( "Metadata: %8d\t%8.2f%%\n", m_metadataSize, (double)m_metadataSize/m_outputFileSize*100);
141 GetSvcLogger()->Printf( "Debugging maps: %8d\t%8.2f%%\n", m_debuggingTableSize, (double)m_debuggingTableSize/m_outputFileSize*100);
142 GetSvcLogger()->Printf( "Hot Code manager: %8d\t%8.2f%%\n", m_hotCodeMgrSize, (double)m_hotCodeMgrSize/m_outputFileSize*100);
143 GetSvcLogger()->Printf( "Unprofiled Code manager: %8d\t%8.2f%%\n", m_unprofiledCodeMgrSize, (double)m_unprofiledCodeMgrSize/m_outputFileSize*100);
144 GetSvcLogger()->Printf( "Cold Code manager: %8d\t%8.2f%%\n", m_coldCodeMgrSize, (double)m_coldCodeMgrSize/m_outputFileSize*100);
145 GetSvcLogger()->Printf( "GC info: %8d\t%8.2f%%\n", m_headerSectionSize, (double)m_headerSectionSize/m_outputFileSize*100);
146 GetSvcLogger()->Printf( "Native code & r/o data: %8d\t%8.2f%%\n", m_codeSectionSize, (double)m_codeSectionSize/m_outputFileSize*100);
147 GetSvcLogger()->Printf( "Cold code: %8d\t%8.2f%%\n", m_coldCodeSectionSize, (double)m_coldCodeSectionSize/m_outputFileSize*100);
148 GetSvcLogger()->Printf( "Exception tables: %8d\t%8.2f%%\n", m_exceptionSectionSize, (double)m_exceptionSectionSize/m_outputFileSize*100);
149 GetSvcLogger()->Printf( "Relocs: %8d\t%8.2f%%\n", m_relocSectionSize, (double)m_relocSectionSize/m_outputFileSize*100);
150 GetSvcLogger()->Printf( "IL metadata: %8d\t%8.2f%%\n", m_ILMetadataSize, (double)m_ILMetadataSize/m_outputFileSize*100);
151 GetSvcLogger()->Printf( "External Method Thunks: %8d\t%8.2f%%\n", m_externalMethodThunkSize, (double)m_externalMethodThunkSize/m_outputFileSize*100);
152 GetSvcLogger()->Printf( "External Method Data: %8d\t%8.2f%%\n", m_externalMethodDataSize, (double)m_externalMethodDataSize/m_outputFileSize*100);
153 GetSvcLogger()->Printf( "Image of EE structures: %8d\t%8.2f%%\n", m_preloadImageSize, (double)m_preloadImageSize/m_outputFileSize*100);
155 unsigned totalIndirections =
156 m_dynamicInfoDelayListSize +
159 m_dynamicInfoTableSize +
162 GetSvcLogger()->Printf( "Indirections: %8d\t%8.2f%%\n",
163 totalIndirections, (double)totalIndirections/m_outputFileSize*100);
164 GetSvcLogger()->Printf( " ----- Breakdown of Indirections ----\n");
166 GetSvcLogger()->Printf( " Delay load lists: %8d\t%8.2f%%\n",
167 m_dynamicInfoDelayListSize, (double)m_dynamicInfoDelayListSize/totalIndirections*100);
168 GetSvcLogger()->Printf( " Tables: %8d\t%8.2f%%\n",
169 m_dynamicInfoTableSize, (double)m_dynamicInfoTableSize/totalIndirections*100);
170 GetSvcLogger()->Printf( " EE Values: %8d\t%8.2f%%\n",
171 m_eeInfoTableSize, (double)m_eeInfoTableSize/totalIndirections*100);
172 GetSvcLogger()->Printf( " Helper functions: %8d\t%8.2f%%\n",
173 m_helperTableSize, (double)m_helperTableSize/totalIndirections*100);
176 GetSvcLogger()->Printf( " Direct method descs:\t%5d/%5d %8.2f%%\n",
177 m_directMethods, m_prestubMethods+m_directMethods,
178 (double)m_directMethods/(m_directMethods+m_prestubMethods)*100);
179 GetSvcLogger()->Printf( " Indirect method descs:\t%5d/%5d %8.2f%%\n",
180 m_prestubMethods, m_prestubMethods+m_directMethods,
181 (double)m_prestubMethods/(m_directMethods+m_prestubMethods)*100);
183 for (int i=0; i < CORINFO_INDIRECT_CALL_COUNT; i++)
184 GetSvcLogger()->Printf( " %-30s %5d %8.2f%%\n",
186 m_indirectMethodReasons[i],
187 double(m_indirectMethodReasons[i])/(m_directMethods+m_prestubMethods)*100);
189 GetSvcLogger()->Printf( "-------------------------------------------------------\n");
190 GetSvcLogger()->Printf( "Total Methods: \t\t\t\t%8d\n", m_methods);
191 GetSvcLogger()->Printf( "Total Hot Only: \t\t\t%8d\n", m_NumHotAllocations);
192 GetSvcLogger()->Printf( "Total Split (Hot/Cold): \t\t%8d\n", m_NumHotColdAllocations);
193 GetSvcLogger()->Printf( "Total Medium Headers: \t\t\t%8d\n", m_NumMediumHeaders);
194 GetSvcLogger()->Printf( "Split Methods: Hot Code \t\t%8d\n", m_nativeCodeSizeInSplitMethods);
195 GetSvcLogger()->Printf( "Split Methods: Cold Code \t\t%8d\n", m_nativeColdCodeSizeInSplitMethods);
196 GetSvcLogger()->Printf( "Split Profiled Methods: Hot Code \t%8d\n", m_nativeCodeSizeInSplitProfiledMethods);
197 GetSvcLogger()->Printf( "Split Profiled Methods: Cold Code \t%8d\n", m_nativeColdCodeSizeInSplitProfiledMethods);
198 GetSvcLogger()->Printf( "Profiled Methods: Hot Code \t\t%8d\n", m_nativeCodeSizeInProfiledMethods);
199 GetSvcLogger()->Printf( "Profiled Methods: Cold Code \t\t%8d\n", m_nativeColdCodeSizeInProfiledMethods);
200 GetSvcLogger()->Printf( "Profiled Methods: Total Hot Code+Headers %7d\n", m_totalCodeSizeInProfiledMethods);
201 GetSvcLogger()->Printf( "Profiled Methods: Total Cold Code+Headers %6d\n", m_totalColdCodeSizeInProfiledMethods);
202 GetSvcLogger()->Printf( "All Methods: Total Hot+Unprofiled Code \t\t%8d\n", m_nativeCodeSize);
203 GetSvcLogger()->Printf( "All Methods: Total Cold Code \t\t%8d\n", m_nativeColdCodeSize);
204 GetSvcLogger()->Printf( "All Methods: Total Hot Code+Headers \t%8d\n", m_totalHotCodeSize);
205 GetSvcLogger()->Printf( "All Methods: Total Unprofiled Code+Headers \t%8d\n", m_totalUnprofiledCodeSize);
206 GetSvcLogger()->Printf( "All Methods: Total Cold Code+Headers \t%8d\n", m_totalColdCodeSize);
208 GetSvcLogger()->Printf( "-------------------------------------------------------\n");
209 GetSvcLogger()->Printf( "Total IL Code: %8d\n", m_ilCodeSize);
210 GetSvcLogger()->Printf( "Total Native Code: %8d\n", m_nativeCodeSize + m_nativeColdCodeSize);
211 GetSvcLogger()->Printf( "Total Code+Headers: %8d\n", m_totalHotCodeSize + m_totalUnprofiledCodeSize + m_totalColdCodeSize);
213 GetSvcLogger()->Printf( "Total Native RO Data: %8d\n", m_nativeRODataSize);
214 GetSvcLogger()->Printf( "Total Native GC Info: %8d\n", m_gcInfoSize);
215 size_t nativeTotal = m_nativeCodeSize + m_nativeRODataSize + m_gcInfoSize;
216 #ifdef WIN64EXCEPTIONS
217 GetSvcLogger()->Printf( "Total Native UnwindInfo:%8d\n", m_unwindInfoSize);
218 nativeTotal += m_unwindInfoSize;
219 #endif // WIN64EXCEPTIONS
220 GetSvcLogger()->Printf( "Total Native Total : %8d\n", nativeTotal);
223 GetSvcLogger()->Printf( "\n");
224 GetSvcLogger()->Printf( "Average IL Code: %8.2f\n", double(m_ilCodeSize) / m_methods);
225 GetSvcLogger()->Printf( "Average NativeCode: %8.2f\n", double(m_nativeCodeSize) / m_methods);
226 GetSvcLogger()->Printf( "Average Native RO Data: %8.2f\n", double(m_nativeRODataSize) / m_methods);
227 GetSvcLogger()->Printf( "Average Native GC Info: %8.2f\n", double(m_gcInfoSize) / m_methods);
228 #ifdef WIN64EXCEPTIONS
229 GetSvcLogger()->Printf( "Average Native UnwindInfo: %8.2f\n", double(m_unwindInfoSize) / m_methods);
230 #endif // WIN64EXCEPTIONS
231 GetSvcLogger()->Printf( "Average Native: %8.2f\n", double(nativeTotal) / m_methods);
232 GetSvcLogger()->Printf( "\n");
233 GetSvcLogger()->Printf( "NativeGC / Native: %8.2f\n", double(m_gcInfoSize) / nativeTotal);
234 GetSvcLogger()->Printf( "Native / IL: %8.2f\n", double(nativeTotal) / m_ilCodeSize);
237 if (m_failedMethods > 0)
238 GetSvcLogger()->Printf( "Methods which did not compile: %d\n", m_failedMethods);
239 if (m_failedILStubs > 0)
240 GetSvcLogger()->Printf( "IL STUBS which did not compile: %d\n", m_failedILStubs);
246 char const * GetCallReasonString( CorInfoIndirectCallReason reason )
248 return callReasons[ reason ];