Skip to content

Commit 2ca4268

Browse files
authored
Additional reflection invoke benchmarks (#4588)
* Additional invoke benchmarks * Add another benchmark + use explicit pre-alloc'd value types
1 parent 0f47692 commit 2ca4268

File tree

1 file changed

+127
-0
lines changed
  • src/benchmarks/micro/runtime/System.Reflection

1 file changed

+127
-0
lines changed

src/benchmarks/micro/runtime/System.Reflection/Invoke.cs

+127
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ public class Invoke
2424
private static MethodInfo s_method_nullableInt;
2525
private static ConstructorInfo s_ctor_int_string_struct_class;
2626
private static ConstructorInfo s_ctor_NoParams;
27+
28+
#if NET8_0_OR_GREATER
29+
private static MethodInvoker s_method_invoker;
30+
private static MethodInvoker s_method_int_string_struct_class_invoker;
31+
private static MethodInvoker s_method_byref_int_string_struct_class_invoker;
32+
private static MethodInvoker s_method_byref_int_string_struct_class_bool_invoker;
33+
private static ConstructorInvoker s_ctor_int_string_struct_class_invoker;
34+
private static ConstructorInvoker s_ctor_NoParams_invoker;
35+
#endif
36+
2737
private static PropertyInfo s_property_int;
2838
private static PropertyInfo s_property_class;
2939
private static FieldInfo s_field_int;
@@ -86,6 +96,15 @@ public void Setup()
8696

8797
s_staticField_struct = typeof(MyClass).
8898
GetField(nameof(MyClass.s_blittableStruct));
99+
100+
#if NET8_0_OR_GREATER
101+
s_method_invoker = MethodInvoker.Create(s_method);
102+
s_method_int_string_struct_class_invoker = MethodInvoker.Create(s_method_int_string_struct_class);
103+
s_method_byref_int_string_struct_class_invoker = MethodInvoker.Create(s_method_byref_int_string_struct_class);
104+
s_method_byref_int_string_struct_class_bool_invoker = MethodInvoker.Create(s_method_byref_int_string_struct_class_bool);
105+
s_ctor_int_string_struct_class_invoker = ConstructorInvoker.Create(s_ctor_int_string_struct_class);
106+
s_ctor_NoParams_invoker = ConstructorInvoker.Create(typeof(MyClass).GetConstructor(Array.Empty<Type>()));
107+
#endif
89108
}
90109

91110
public static void Method_int_string_struct_class(int i, string s, MyBlittableStruct myStruct, MyClass myClass)
@@ -122,6 +141,18 @@ public void Method0_NoParms()
122141
}
123142
}
124143

144+
145+
#if NET8_0_OR_GREATER
146+
[Benchmark(OperationsPerInvoke = Iterations)]
147+
public void Method0_NoParms_MethodInvoker()
148+
{
149+
for (int i = 0; i < Iterations; i++)
150+
{
151+
s_method_invoker.Invoke(s_MyClass);
152+
}
153+
}
154+
#endif
155+
125156
[Benchmark(OperationsPerInvoke = Iterations)]
126157
// Include the array allocation and population for a typical scenario.
127158
public void StaticMethod4_arrayNotCached_int_string_struct_class()
@@ -154,6 +185,32 @@ public void StaticMethod4_int_string_struct_class()
154185
}
155186
}
156187

188+
#if NET8_0_OR_GREATER
189+
[Benchmark(OperationsPerInvoke = Iterations)]
190+
public void StaticMethod4_int_string_struct_class_MethodInvoker()
191+
{
192+
// To make the test more comparable to the MethodBase tests, set up the references and pre-boxed types.
193+
object boxedInt = s_args4[0];
194+
object stringRef = s_args4[1];
195+
object boxedStruct = s_args4[2];
196+
object myClassRef = s_args4[3];
197+
198+
for (int i = 0; i < Iterations; i++)
199+
{
200+
s_method_int_string_struct_class_invoker.Invoke(null, boxedInt, stringRef, boxedStruct, myClassRef);
201+
}
202+
}
203+
204+
[Benchmark(OperationsPerInvoke = Iterations)]
205+
public void StaticMethod4_int_string_struct_class_MethodInvokerWithSpan()
206+
{
207+
for (int i = 0; i < Iterations; i++)
208+
{
209+
s_method_int_string_struct_class_invoker.Invoke(null, new Span<object>(s_args4));
210+
}
211+
}
212+
#endif
213+
157214
[Benchmark(OperationsPerInvoke = Iterations)]
158215
public void StaticMethod4_ByRefParams_int_string_struct_class()
159216
{
@@ -163,6 +220,23 @@ public void StaticMethod4_ByRefParams_int_string_struct_class()
163220
}
164221
}
165222

223+
#if NET8_0_OR_GREATER
224+
[Benchmark(OperationsPerInvoke = Iterations)]
225+
public void StaticMethod4_ByRefParams_int_string_struct_class_MethodInvoker()
226+
{
227+
// To make the test more comparable to the MethodBase tests, set up the references and pre-boxed types.
228+
object boxedInt = s_args4[0];
229+
object stringRef = s_args4[1];
230+
object boxedStruct = s_args4[2];
231+
object myClassRef = s_args4[3];
232+
233+
for (int i = 0; i < Iterations; i++)
234+
{
235+
s_method_byref_int_string_struct_class_invoker.Invoke(null, boxedInt, stringRef, boxedStruct, myClassRef);
236+
}
237+
}
238+
#endif
239+
166240
[Benchmark(OperationsPerInvoke = Iterations)]
167241
// Starting with 5 parameters, stack allocations are replaced with heap allocations.
168242
public void StaticMethod5_ByRefParams_int_string_struct_class_bool()
@@ -173,6 +247,17 @@ public void StaticMethod5_ByRefParams_int_string_struct_class_bool()
173247
}
174248
}
175249

250+
#if NET8_0_OR_GREATER
251+
[Benchmark(OperationsPerInvoke = Iterations)]
252+
public void StaticMethod5_ByRefParams_int_string_struct_class_bool_MethodInvoker()
253+
{
254+
for (int i = 0; i < Iterations; i++)
255+
{
256+
s_method_byref_int_string_struct_class_bool_invoker.Invoke(null, new Span<object>(s_args5));
257+
}
258+
}
259+
#endif
260+
176261
[Benchmark(OperationsPerInvoke = Iterations)]
177262
public void Ctor0_NoParams()
178263
{
@@ -182,6 +267,31 @@ public void Ctor0_NoParams()
182267
}
183268
}
184269

270+
#if NET8_0_OR_GREATER
271+
[Benchmark(OperationsPerInvoke = Iterations)]
272+
public void Ctor0_NoParams_ConstructorInvoker()
273+
{
274+
for (int i = 0; i < Iterations; i++)
275+
{
276+
s_ctor_NoParams_invoker.Invoke();
277+
}
278+
}
279+
#endif
280+
281+
/// <summary>
282+
/// Reinvoke the constructor on the same object. Used by some serializers.
283+
/// </summary>
284+
[Benchmark(OperationsPerInvoke = Iterations)]
285+
public void Ctor0_NoParams_Reinvoke()
286+
{
287+
MyClass obj = new MyClass();
288+
289+
for (int i = 0; i < Iterations; i++)
290+
{
291+
s_ctor_NoParams.Invoke(obj, null);
292+
}
293+
}
294+
185295
[Benchmark(OperationsPerInvoke = Iterations)]
186296
public void Ctor0_ActivatorCreateInstance_NoParams()
187297
{
@@ -200,6 +310,23 @@ public void Ctor4_int_string_struct_class()
200310
}
201311
}
202312

313+
#if NET8_0_OR_GREATER
314+
[Benchmark(OperationsPerInvoke = Iterations)]
315+
public void Ctor4_int_string_struct_class_ConstructorInvoker()
316+
{
317+
// To make the test more comparable to the MethodBase tests, set up the references and pre-boxed types.
318+
object boxedInt = s_args4[0];
319+
object stringRef = s_args4[1];
320+
object boxedStruct = s_args4[2];
321+
object myClassRef = s_args4[3];
322+
323+
for (int i = 0; i < Iterations; i++)
324+
{
325+
s_ctor_int_string_struct_class_invoker.Invoke(boxedInt, stringRef, boxedStruct, myClassRef);
326+
}
327+
}
328+
#endif
329+
203330
[Benchmark(OperationsPerInvoke = Iterations)]
204331
public void Ctor4_ActivatorCreateInstance()
205332
{

0 commit comments

Comments
 (0)