55using System . Reflection ;
66using System . Runtime . CompilerServices ;
77using System . Text ;
8- using System . Threading . Tasks ;
98using BenchmarkDotNet . Characteristics ;
109using BenchmarkDotNet . Diagnosers ;
1110using BenchmarkDotNet . Disassemblers ;
@@ -33,29 +32,17 @@ internal static string Generate(BuildPartition buildPartition)
3332 {
3433 var benchmark = buildInfo . BenchmarkCase ;
3534
36- var provider = GetDeclarationsProvider ( benchmark . Descriptor ) ;
37-
38- string passArguments = GetPassArguments ( benchmark ) ;
39-
40- string benchmarkTypeCode = new SmartStringBuilder ( ResourceHelper . LoadTemplate ( "BenchmarkType.txt" ) )
35+ string benchmarkTypeCode = GetDeclarationsProvider ( benchmark )
36+ . ReplaceTemplate ( new SmartStringBuilder ( ResourceHelper . LoadTemplate ( "BenchmarkType.txt" ) ) )
4137 . Replace ( "$ID$" , buildInfo . Id . ToString ( ) )
42- . Replace ( "$OperationsPerInvoke$" , provider . OperationsPerInvoke )
43- . Replace ( "$WorkloadTypeName$" , provider . WorkloadTypeName )
44- . Replace ( "$GlobalSetupMethodName$" , provider . GlobalSetupMethodName )
45- . Replace ( "$GlobalCleanupMethodName$" , provider . GlobalCleanupMethodName )
46- . Replace ( "$IterationSetupMethodName$" , provider . IterationSetupMethodName )
47- . Replace ( "$IterationCleanupMethodName$" , provider . IterationCleanupMethodName )
4838 . Replace ( "$JobSetDefinition$" , GetJobsSetDefinition ( benchmark ) )
4939 . Replace ( "$ParamsContent$" , GetParamsContent ( benchmark ) )
5040 . Replace ( "$ArgumentsDefinition$" , GetArgumentsDefinition ( benchmark ) )
5141 . Replace ( "$DeclareArgumentFields$" , GetDeclareArgumentFields ( benchmark ) )
5242 . Replace ( "$InitializeArgumentFields$" , GetInitializeArgumentFields ( benchmark ) )
53- . Replace ( "$LoadArguments$" , GetLoadArguments ( benchmark ) )
54- . Replace ( "$PassArguments$" , passArguments )
5543 . Replace ( "$EngineFactoryType$" , GetEngineFactoryTypeName ( benchmark ) )
5644 . Replace ( "$RunExtraIteration$" , buildInfo . Config . HasExtraIterationDiagnoser ( benchmark ) ? "true" : "false" )
5745 . Replace ( "$DisassemblerEntryMethodName$" , DisassemblerConstants . DisassemblerEntryMethodName )
58- . Replace ( "$WorkloadMethodCall$" , provider . GetWorkloadMethodCall ( passArguments ) )
5946 . Replace ( "$InProcessDiagnoserRouters$" , GetInProcessDiagnoserRouters ( buildInfo ) )
6047 . ToString ( ) ;
6148
@@ -132,27 +119,21 @@ private static string GetJobsSetDefinition(BenchmarkCase benchmarkCase)
132119 Replace ( "; " , ";\n " ) ;
133120 }
134121
135- private static DeclarationsProvider GetDeclarationsProvider ( Descriptor descriptor )
122+ private static DeclarationsProvider GetDeclarationsProvider ( BenchmarkCase benchmark )
136123 {
137- var method = descriptor . WorkloadMethod ;
124+ var method = benchmark . Descriptor . WorkloadMethod ;
138125
139- if ( method . ReturnType == typeof ( Task ) || method . ReturnType == typeof ( ValueTask ) )
140- {
141- return new AsyncDeclarationsProvider ( descriptor ) ;
142- }
143- if ( method . ReturnType . GetTypeInfo ( ) . IsGenericType
144- && ( method . ReturnType . GetTypeInfo ( ) . GetGenericTypeDefinition ( ) == typeof ( Task < > )
145- || method . ReturnType . GetTypeInfo ( ) . GetGenericTypeDefinition ( ) == typeof ( ValueTask < > ) ) )
126+ if ( method . ReturnType . IsAwaitable ( ) )
146127 {
147- return new AsyncDeclarationsProvider ( descriptor ) ;
128+ return new AsyncDeclarationsProvider ( benchmark ) ;
148129 }
149130
150131 if ( method . ReturnType == typeof ( void ) && method . HasAttribute < AsyncStateMachineAttribute > ( ) )
151132 {
152133 throw new NotSupportedException ( "async void is not supported by design" ) ;
153134 }
154135
155- return new SyncDeclarationsProvider ( descriptor ) ;
136+ return new SyncDeclarationsProvider ( benchmark ) ;
156137 }
157138
158139 // internal for tests
@@ -168,31 +149,19 @@ private static string GetArgumentsDefinition(BenchmarkCase benchmarkCase)
168149 => string . Join (
169150 ", " ,
170151 benchmarkCase . Descriptor . WorkloadMethod . GetParameters ( )
171- . Select ( ( parameter , index ) => $ "{ GetParameterModifier ( parameter ) } { parameter . ParameterType . GetCorrectCSharpTypeName ( ) } arg{ index } ") ) ;
152+ . Select ( ( parameter , index ) => $ "{ GetParameterModifier ( parameter ) } { parameter . ParameterType . GetCorrectCSharpTypeName ( ) } arg{ index } ") ) ;
172153
173154 private static string GetDeclareArgumentFields ( BenchmarkCase benchmarkCase )
174155 => string . Join (
175156 Environment . NewLine ,
176157 benchmarkCase . Descriptor . WorkloadMethod . GetParameters ( )
177- . Select ( ( parameter , index ) => $ "private { GetFieldType ( parameter . ParameterType , benchmarkCase . Parameters . GetArgument ( parameter . Name ) ) . GetCorrectCSharpTypeName ( ) } __argField{ index } ;") ) ;
158+ . Select ( ( parameter , index ) => $ "public { GetFieldType ( parameter . ParameterType , benchmarkCase . Parameters . GetArgument ( parameter . Name ) ) . GetCorrectCSharpTypeName ( ) } __argField{ index } ;") ) ;
178159
179160 private static string GetInitializeArgumentFields ( BenchmarkCase benchmarkCase )
180161 => string . Join (
181162 Environment . NewLine ,
182163 benchmarkCase . Descriptor . WorkloadMethod . GetParameters ( )
183- . Select ( ( parameter , index ) => $ "this.__argField{ index } = { benchmarkCase . Parameters . GetArgument ( parameter . Name ) . ToSourceCode ( ) } ;") ) ; // we init the fields in ctor to provoke all possible allocations and overhead of other type
184-
185- private static string GetLoadArguments ( BenchmarkCase benchmarkCase )
186- => string . Join (
187- Environment . NewLine ,
188- benchmarkCase . Descriptor . WorkloadMethod . GetParameters ( )
189- . Select ( ( parameter , index ) => $ "{ ( parameter . ParameterType . IsByRef ? "ref" : string . Empty ) } { parameter . ParameterType . GetCorrectCSharpTypeName ( ) } arg{ index } = { ( parameter . ParameterType . IsByRef ? "ref" : string . Empty ) } this.__argField{ index } ;") ) ;
190-
191- private static string GetPassArguments ( BenchmarkCase benchmarkCase )
192- => string . Join (
193- ", " ,
194- benchmarkCase . Descriptor . WorkloadMethod . GetParameters ( )
195- . Select ( ( parameter , index ) => $ "{ GetParameterModifier ( parameter ) } arg{ index } ") ) ;
164+ . Select ( ( parameter , index ) => $ "this.__fieldsContainer.__argField{ index } = { benchmarkCase . Parameters . GetArgument ( parameter . Name ) . ToSourceCode ( ) } ;") ) ; // we init the fields in ctor to provoke all possible allocations and overhead of other type
196165
197166 private static string GetExtraAttributes ( Descriptor descriptor )
198167 => descriptor . WorkloadMethod . GetCustomAttributes ( false ) . OfType < STAThreadAttribute > ( ) . Any ( ) ? "[System.STAThreadAttribute]" : string . Empty ;
@@ -235,7 +204,7 @@ private static string GetInProcessDiagnoserRouters(BenchmarkBuildInfo buildInfo)
235204 }
236205 }
237206
238- private static string GetParameterModifier ( ParameterInfo parameterInfo )
207+ internal static string GetParameterModifier ( ParameterInfo parameterInfo )
239208 {
240209 if ( ! parameterInfo . ParameterType . IsByRef )
241210 return string . Empty ;
@@ -263,7 +232,7 @@ private static string GetNativeAotSwitch(BuildPartition buildPartition)
263232 @switch . AppendLine ( "switch (id) {" ) ;
264233
265234 foreach ( var buildInfo in buildPartition . Benchmarks )
266- @switch . AppendLine ( $ "case { buildInfo . Id . Value } : BenchmarkDotNet.Autogenerated.Runnable_{ buildInfo . Id . Value } .Run(host, benchmarkName, diagnoserRunMode); break;") ;
235+ @switch . AppendLine ( $ "case { buildInfo . Id . Value } : runTask = BenchmarkDotNet.Autogenerated.Runnable_{ buildInfo . Id . Value } .Run(host, benchmarkName, diagnoserRunMode); break;") ;
267236
268237 @switch . AppendLine ( "default: throw new System.NotSupportedException(\" invalid benchmark id\" );" ) ;
269238 @switch . AppendLine ( "}" ) ;
@@ -279,28 +248,21 @@ private static Type GetFieldType(Type argumentType, ParameterInstance argument)
279248
280249 return argumentType ;
281250 }
251+ }
282252
283- private class SmartStringBuilder
284- {
285- private readonly string originalText ;
286- private readonly StringBuilder builder ;
287-
288- public SmartStringBuilder ( string text )
289- {
290- originalText = text ;
291- builder = new StringBuilder ( text ) ;
292- }
293-
294- public SmartStringBuilder Replace ( string oldValue , string ? newValue )
295- {
296- if ( originalText . Contains ( oldValue ) )
297- builder . Replace ( oldValue , newValue ) ;
298- else
299- builder . Append ( $ "\n // '{ oldValue } ' not found") ;
300- return this ;
301- }
253+ internal class SmartStringBuilder ( string text )
254+ {
255+ private readonly StringBuilder builder = new ( text ) ;
302256
303- public override string ToString ( ) => builder . ToString ( ) ;
257+ public SmartStringBuilder Replace ( string oldValue , string ? newValue )
258+ {
259+ if ( text . Contains ( oldValue ) )
260+ builder . Replace ( oldValue , newValue ) ;
261+ else
262+ builder . Append ( $ "\n // '{ oldValue } ' not found") ;
263+ return this ;
304264 }
265+
266+ public override string ToString ( ) => builder . ToString ( ) ;
305267 }
306268}
0 commit comments