Type.GetCustomAttributes()
can be slow when not passing an attributeType
parameter. #89928
Open
Description
opened on Aug 3, 2023
Consider the following benchmark:
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System.Reflection;
using System.Runtime.CompilerServices;
BenchmarkRunner.Run<MyBench>(args: args);
public class MyBench
{
private readonly Type _type = typeof(ValueType);
private readonly Type _requiredMemberAttribute = typeof(RequiredMemberAttribute);
[Benchmark(Baseline = true)]
public RequiredMemberAttribute? GetCustomAttributeTypeArgument()
{
return (RequiredMemberAttribute?)_type.GetCustomAttributes(_requiredMemberAttribute, inherit: false).FirstOrDefault();
}
[Benchmark]
public RequiredMemberAttribute? GetCustomAttributeNoTypeArgument()
{
foreach (object attribute in _type.GetCustomAttributes(inherit: false))
{
if (attribute.GetType() == _requiredMemberAttribute)
{
return (RequiredMemberAttribute)attribute;
}
}
return null;
}
[Benchmark]
public CustomAttributeData? GetCustomAttributesData()
{
foreach (CustomAttributeData attrData in _type.GetCustomAttributesData())
{
if (attrData.AttributeType == _requiredMemberAttribute)
{
return attrData;
}
}
return null;
}
}
Method | Mean | Error | StdDev | Ratio | RatioSD |
---|---|---|---|---|---|
GetCustomAttributeTypeArgument | 388.8 ns | 2.48 ns | 2.32 ns | 1.00 | 0.00 |
GetCustomAttributeNoTypeArgument | 1,932.7 ns | 10.42 ns | 9.24 ns | 4.97 | 0.04 |
GetCustomAttributesData | 3,759.0 ns | 26.10 ns | 21.80 ns | 9.67 | 0.09 |
Discovered while investigating #89794
Activity