.NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)

阅读: 评论:0

.NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)

.NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)

大家都说反射耗性能,但是到底有多耗性能,哪些反射方法更耗性能;这些问题却没有统一的描述。

本文将用数据说明反射各个方法和替代方法的性能差异,并提供一些反射代码的编写建议。为了解决反射的性能问题,你可以遵循本文采用的各种方案。


本文内容

      • 反射各方法的性能数据
      • 反射的高性能开发建议
        • 创建类型的实例
        • 反射获取 Attribute
        • 反射调用公共 / 私有方法
        • 使用预编译框架
      • 附本文性能测试所用的代码
        • 所有反射相关方法
        • IsDefined 和 GetCustomAttribute 的专项比较
        • 参考资料

反射各方法的性能数据

我使用 BenchmarkDotNet 基准性能测试来评估反射各个方法的性能。测试的程序基于 .NET Core 2.1 开发。

先直观地贴出我的运行结果:


▲ 各反射不同方法的运行基准测试结果

我把上面的表格复制下来成为文字,这样你也可以拿走我的这部分数据:

MethodMeanErrorStdDevMedian
Assembly13.5315 ns0.3004 ns0.4764 ns13.4878 ns
Attributes7.0893 ns0.1248 ns0.1168 ns7.0982 ns
CustomAttributes1,489.1654 ns29.4428 ns27.5408 ns1,482.5038 ns
GetCustomAttributesData1,514.5503 ns29.6863 ns39.6303 ns1,507.2949 ns
GetCustomAttributes1,171.8969 ns22.5305 ns27.6695 ns1,167.2777 ns
GetCustomAttribute1,139.8609 ns22.8043 ns24.4003 ns1,140.5437 ns
GetCustomAttribute_Generic1,115.0049 ns13.1929 ns11.6952 ns1,111.4426 ns
GetCustomAttributes_Generic1,164.5132 ns22.7775 ns24.3716 ns1,165.2747 ns
New0.0003 ns0.0013 ns0.0012 ns0.0000 ns
Lambda0.0063 ns0.0149 ns0.0139 ns0.0000 ns
Activator_CreateInstance48.8633 ns0.6300 ns0.5893 ns48.8906 ns
Activator_CreateInstance_Generic47.7029 ns0.9649 ns1.0724 ns47.5851 ns
Expression_New75,634.4035 ns1,467.3285 ns1,372.5400 ns75,413.2837 ns
CachedExpression_New7.8923 ns0.1988 ns0.4105 ns7.7004 ns

如果你希望了解以上每一项的意思,可以通过阅读本文文末的代码来了解其实现。基本上名称就代表着反射调用相同的方法。

你一定会说这张表不容易看出性能差距。那么我一定会放图:

那个 Expression_New 在图中独树一帜,远远把其他方法甩在了后面。那是个什么方法?

那是在使用 Expression 表达式创建一个类型的新实例:

var @new = Expression.New(typeof(ReflectionTarget));
var lambda = Expression.Lambda<Func<ReflectionTarget>>(@new).Compile();
var instance = lambda.Invoke();

也就是说,如果你只是希望创建一个类型的新实例,就不要考虑使用 Expression.New 的方式了。除非此方法将执行非常多次,而你把那个 lambda 表达式缓存下来了。这对应着图表中的 CachedExpression_New

其他的现在都看不出来性能差异,于是我们把耗时最长的 Expression_New 一项去掉:

我们立刻可以从图中得到第二梯队的性能巨头 —— 就是 CustomAttributes 系列。我使用了多种不同的 CustomAttribute 获取方法,得到的结果差异不大,都“比较耗时”。不过在这些耗时的方法里面找到不那么耗时的,就是 Type 的扩展方法系列 GetCustomAttribute 了,比原生非扩展方法的性能稍好。

不过其他的性能差异又被淹没了。于是我们把 CustomAttributes 系列也删掉:

于是我们又得到了第三梯队的性能大头 —— Activator.CreateInstance 系列。而是否调用泛型方法的耗时差异不大。

然后,我们把 Activator.CreateInstance 也干掉,可以得到剩下其他的性能消耗。

也就是说,只是获取 Type 中的一些属性,例如 AssemblyAttributes 也是比较“耗时”的;当然,这是纳秒级别,你可以将它忽略。

要不要试试把第四梯队的也干掉呢?于是你可以得到 newLambda 的差异:

原本在上面所有图中看起来都没有时间的 newLambda 竟然差异如此巨大;不过,这都是千分之一纳秒级别了;如果你创建的类数量不是百万级别以上,你还真的可以忽略。

new 指的是 new

本文发布于:2024-02-02 02:55:28,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170681572740940.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:反射   高性能   性能   建议   方法
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23