Skip to content

Additional reflection invoke benchmarks #4588

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 5, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading