Skip to content
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

Additional reflection invoke benchmarks #4588

Merged
merged 3 commits into from
Feb 5, 2025
Merged
Changes from 2 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
112 changes: 112 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,15 @@ 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
carlossanlop marked this conversation as resolved.
Show resolved Hide resolved
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 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 +95,14 @@ 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_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 +139,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 +183,34 @@ 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, we need to pre-box the value types.
object boxedInt = 42;
object boxedStruct = default(MyBlittableStruct);

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

[Benchmark(OperationsPerInvoke = Iterations)]
public void StaticMethod4_int_string_struct_class_MethodInvokerWithSpan()
{
// To make the test more comparable to the MethodBase tests, we need to pre-box the value types.
object boxedInt = 42;
object boxedStruct = default(MyBlittableStruct);

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,21 @@ 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, we need to pre-box the value types.
object boxedInt = 42;
object boxedStruct = default(MyBlittableStruct);

for (int i = 0; i < Iterations; i++)
{
s_method_byref_int_string_struct_class_invoker.Invoke(null, boxedInt, "Hello", boxedStruct, s_MyClass);
}
}
#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 @@ -182,6 +254,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 +297,21 @@ 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, we need to pre-box the value types.
object boxedInt = 42;
object boxedStruct = default(MyBlittableStruct);
steveharter marked this conversation as resolved.
Show resolved Hide resolved

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

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