Skip to content

Commit

Permalink
Additional reflection invoke benchmarks (#4588)
Browse files Browse the repository at this point in the history
* Additional invoke benchmarks

* Add another benchmark + use explicit pre-alloc'd value types
  • Loading branch information
steveharter authored Feb 5, 2025
1 parent 0f47692 commit 2ca4268
Showing 1 changed file with 127 additions and 0 deletions.
127 changes: 127 additions & 0 deletions src/benchmarks/micro/runtime/System.Reflection/Invoke.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ public class Invoke
private static MethodInfo s_method_nullableInt;
private static ConstructorInfo s_ctor_int_string_struct_class;
private static ConstructorInfo s_ctor_NoParams;

#if NET8_0_OR_GREATER
private static MethodInvoker s_method_invoker;
private static MethodInvoker s_method_int_string_struct_class_invoker;
private static MethodInvoker s_method_byref_int_string_struct_class_invoker;
private static MethodInvoker s_method_byref_int_string_struct_class_bool_invoker;
private static ConstructorInvoker s_ctor_int_string_struct_class_invoker;
private static ConstructorInvoker s_ctor_NoParams_invoker;
#endif

private static PropertyInfo s_property_int;
private static PropertyInfo s_property_class;
private static FieldInfo s_field_int;
Expand Down Expand Up @@ -86,6 +96,15 @@ public void Setup()

s_staticField_struct = typeof(MyClass).
GetField(nameof(MyClass.s_blittableStruct));

#if NET8_0_OR_GREATER
s_method_invoker = MethodInvoker.Create(s_method);
s_method_int_string_struct_class_invoker = MethodInvoker.Create(s_method_int_string_struct_class);
s_method_byref_int_string_struct_class_invoker = MethodInvoker.Create(s_method_byref_int_string_struct_class);
s_method_byref_int_string_struct_class_bool_invoker = MethodInvoker.Create(s_method_byref_int_string_struct_class_bool);
s_ctor_int_string_struct_class_invoker = ConstructorInvoker.Create(s_ctor_int_string_struct_class);
s_ctor_NoParams_invoker = ConstructorInvoker.Create(typeof(MyClass).GetConstructor(Array.Empty<Type>()));
#endif
}

public static void Method_int_string_struct_class(int i, string s, MyBlittableStruct myStruct, MyClass myClass)
Expand Down Expand Up @@ -122,6 +141,18 @@ public void Method0_NoParms()
}
}


#if NET8_0_OR_GREATER
[Benchmark(OperationsPerInvoke = Iterations)]
public void Method0_NoParms_MethodInvoker()
{
for (int i = 0; i < Iterations; i++)
{
s_method_invoker.Invoke(s_MyClass);
}
}
#endif

[Benchmark(OperationsPerInvoke = Iterations)]
// Include the array allocation and population for a typical scenario.
public void StaticMethod4_arrayNotCached_int_string_struct_class()
Expand Down Expand Up @@ -154,6 +185,32 @@ public void StaticMethod4_int_string_struct_class()
}
}

#if NET8_0_OR_GREATER
[Benchmark(OperationsPerInvoke = Iterations)]
public void StaticMethod4_int_string_struct_class_MethodInvoker()
{
// To make the test more comparable to the MethodBase tests, set up the references and pre-boxed types.
object boxedInt = s_args4[0];
object stringRef = s_args4[1];
object boxedStruct = s_args4[2];
object myClassRef = s_args4[3];

for (int i = 0; i < Iterations; i++)
{
s_method_int_string_struct_class_invoker.Invoke(null, boxedInt, stringRef, boxedStruct, myClassRef);
}
}

[Benchmark(OperationsPerInvoke = Iterations)]
public void StaticMethod4_int_string_struct_class_MethodInvokerWithSpan()
{
for (int i = 0; i < Iterations; i++)
{
s_method_int_string_struct_class_invoker.Invoke(null, new Span<object>(s_args4));
}
}
#endif

[Benchmark(OperationsPerInvoke = Iterations)]
public void StaticMethod4_ByRefParams_int_string_struct_class()
{
Expand All @@ -163,6 +220,23 @@ public void StaticMethod4_ByRefParams_int_string_struct_class()
}
}

#if NET8_0_OR_GREATER
[Benchmark(OperationsPerInvoke = Iterations)]
public void StaticMethod4_ByRefParams_int_string_struct_class_MethodInvoker()
{
// To make the test more comparable to the MethodBase tests, set up the references and pre-boxed types.
object boxedInt = s_args4[0];
object stringRef = s_args4[1];
object boxedStruct = s_args4[2];
object myClassRef = s_args4[3];

for (int i = 0; i < Iterations; i++)
{
s_method_byref_int_string_struct_class_invoker.Invoke(null, boxedInt, stringRef, boxedStruct, myClassRef);
}
}
#endif

[Benchmark(OperationsPerInvoke = Iterations)]
// Starting with 5 parameters, stack allocations are replaced with heap allocations.
public void StaticMethod5_ByRefParams_int_string_struct_class_bool()
Expand All @@ -173,6 +247,17 @@ public void StaticMethod5_ByRefParams_int_string_struct_class_bool()
}
}

#if NET8_0_OR_GREATER
[Benchmark(OperationsPerInvoke = Iterations)]
public void StaticMethod5_ByRefParams_int_string_struct_class_bool_MethodInvoker()
{
for (int i = 0; i < Iterations; i++)
{
s_method_byref_int_string_struct_class_bool_invoker.Invoke(null, new Span<object>(s_args5));
}
}
#endif

[Benchmark(OperationsPerInvoke = Iterations)]
public void Ctor0_NoParams()
{
Expand All @@ -182,6 +267,31 @@ public void Ctor0_NoParams()
}
}

#if NET8_0_OR_GREATER
[Benchmark(OperationsPerInvoke = Iterations)]
public void Ctor0_NoParams_ConstructorInvoker()
{
for (int i = 0; i < Iterations; i++)
{
s_ctor_NoParams_invoker.Invoke();
}
}
#endif

/// <summary>
/// Reinvoke the constructor on the same object. Used by some serializers.
/// </summary>
[Benchmark(OperationsPerInvoke = Iterations)]
public void Ctor0_NoParams_Reinvoke()
{
MyClass obj = new MyClass();

for (int i = 0; i < Iterations; i++)
{
s_ctor_NoParams.Invoke(obj, null);
}
}

[Benchmark(OperationsPerInvoke = Iterations)]
public void Ctor0_ActivatorCreateInstance_NoParams()
{
Expand All @@ -200,6 +310,23 @@ public void Ctor4_int_string_struct_class()
}
}

#if NET8_0_OR_GREATER
[Benchmark(OperationsPerInvoke = Iterations)]
public void Ctor4_int_string_struct_class_ConstructorInvoker()
{
// To make the test more comparable to the MethodBase tests, set up the references and pre-boxed types.
object boxedInt = s_args4[0];
object stringRef = s_args4[1];
object boxedStruct = s_args4[2];
object myClassRef = s_args4[3];

for (int i = 0; i < Iterations; i++)
{
s_ctor_int_string_struct_class_invoker.Invoke(boxedInt, stringRef, boxedStruct, myClassRef);
}
}
#endif

[Benchmark(OperationsPerInvoke = Iterations)]
public void Ctor4_ActivatorCreateInstance()
{
Expand Down

0 comments on commit 2ca4268

Please sign in to comment.