.Net 7内容汇总(3)--反射优化
反射这玩意,一直以来都是慢的代名词。一说XXX系统大量的反射,好多人第一印象就是会慢。
但是呢,我们又不得不使用反射来做一些事情,毕竟这玩意可以说啥都能干了对吧。
It’s immensely powerful, providing the ability to query all of the metadata for code in your process and for arbitrary assemblies you might encounter, to invoke arbitrary functionality dynamically, and even to emit dynamically-generated IL at run-time.
当然.Net也提供了一些性能更高的方法。
比如SG,这玩意是性能最好的方案,它在编译的时候生成代码,运行的时候一点反射没有,同时也完美支持Native AOT。但是呢,它还不是真正的动态生成,只能说是开发时动态。所以更适合一些框架程序使用来提高执行效率。
还有比如Emit,这玩意是动态编织IL代码的,效率也比反射要快。但是呢,写起来极度复杂,10个人有8个都挠头。
所以,.Net 7里反射还是非常重要的一部分,也针对它做了一些比较牛逼的优化。
我们知道,给
MethodBase使用CreateDelegate<T>来创建一个委托,然后调用这个委托是最佳方法。但是呢,我们编译的时候经常是不知道这个方法签名的,也就是没法生成这个委托。部分库已经使用Emit来生成代码提高速度了。但是我们普通用户显然区写一堆Emit是不现实的。.Net 7优化后,会把我们的反射代码优化为DynamicMethod形式的委托,然后调用。我们来看一下数据
private MethodInfo _method;
[GlobalSetup]
public void Setup() => _method = typeof(Program).GetMethod("MyMethod", BindingFlags.NonPublic | BindingFlags.Static);
[Benchmark]
public void MethodInfoInvoke() => _method.Invoke(null, null);
private static void MyMethod() { }
|
Method |
Runtime |
Mean |
Ratio |
|---|---|---|---|
|
MethodInfoInvoke |
.NET 6.0 |
43.846 ns |
1.00 |
|
MethodInfoInvoke |
.NET 7.0 |
8.078 ns |
0.18 |
我们可以看到,这玩意速度提升了好几倍。
反射还有一个用处就是对类型、方法、属性等等这些东西进行获取。一些其他的改进也会影响到这一部分。比如.Net最近一直在做的把原生类型转换为托管类型的工作,就产生了这么一个东西。
[Benchmark]
public Type GetUnderlyingType() => Enum.GetUnderlyingType(typeof(DayOfWeek));
|
Method |
Runtime |
Mean |
Ratio |
|---|---|---|---|
|
GetUnderlyingType |
.NET 6.0 |
27.413 ns |
1.00 |
|
GetUnderlyingType |
.NET 7.0 |
5.115 ns |
0.19 |
是的,原生类型转换为托管类型,不但没有拖慢反射,反而让它快了好几倍。
同样的例子,有大量的AssemblyName的内容从原生转向了CoreLib,所以Activator.CreateInstance也跟着变快了。
private readonly string _assemblyName = typeof(MyClass).Assembly.FullName;
private readonly string _typeName = typeof(MyClass).FullName;
public class MyClass { }
[Benchmark]
public object CreateInstance() => Activator.CreateInstance(_assemblyName, _typeName);
|
Method |
Runtime |
Mean |
Ratio |
|---|---|---|---|
|
CreateInstance |
.NET 6.0 |
3.827 us |
1.00 |
|
CreateInstance |
.NET 7.0 |
2.276 us |
0.60 |
这玩意虽然没有那么夸张,但是提升可以说也是不小了。
RuntimeType.CreateInstanceImpl现在使用Type.EmptyTypes代替了new Type[0],所以节省了一部分开销。
[Benchmark]
public void CreateInstance() => Activator.CreateInstance(typeof(MyClass), BindingFlags.NonPublic | BindingFlags.Instance, null, Array.Empty<object>(), null);
internal class MyClass
{
internal MyClass() { }
}
|
Method |
Runtime |
Mean |
Ratio |
Allocated |
Alloc Ratio |
|---|---|---|---|---|---|
|
CreateInstance |
.NET 6.0 |
167.8 ns |
1.00 |
320 B |
1.00 |
|
CreateInstance |
.NET 7.0 |
143.4 ns |
0.85 |
200 B |
0.62 |
我们再回到AssemblyName来,AssemblyName里把AssemblyName.FullName的实现由StringBuilder改为了ArrayPool<char>,所以:
private AssemblyName[] _names = AppDomain.CurrentDomain.GetAssemblies().Select(a => new AssemblyName(a.FullName)).ToArray();
[Benchmark]
public int Names()
{
int sum = 0;
foreach (AssemblyName name in _names)
{
sum += name.FullName.Length;
}
return sum;
}
|
Method |
Runtime |
Mean |
Ratio |
Allocated |
Alloc Ratio |
|---|---|---|---|---|---|
|
Names |
.NET 6.0 |
3.423 us |
1.00 |
9.14 KB |
1.00 |
|
Names |
.NET 7.0 |
2.010 us |
0.59 |
2.43 KB |
0.27 |
另外由于JIT编译器又进化了,现在可以在编译过程中计算结果,所以:
[Benchmark]
public bool IsByRefLike() => typeof(ReadOnlySpan<char>).IsByRefLike;
|
Method |
Runtime |
Mean |
Ratio |
Code Size |
|---|---|---|---|---|
|
IsByRefLike |
.NET 6.0 |
2.1322 ns |
1.00 |
31 B |
|
IsByRefLike |
.NET 7.0 |
0.0000 ns |
0.00 |
6B |
是的,你没看错,时间是0,因为这里在运行的时候已经不需要计算了,直接就是个赋值操作,所以这个时间就。。。
我们来看一下生成的汇编
; Program.IsByRefLike()
mov eax,1
ret
; Total bytes of code 6
这就是反射优化的主要内容。反正就高喊666,知道反射又快了,用起来心里负担又小了就搞定了^ ^。
.Net 7内容汇总(3)--反射优化的更多相关文章
- 反射-优化及程序集等(用委托的方式调用需要反射调用的方法(或者属性、字段),而不去使用Invoke方法)
反射-优化及程序集等(用委托的方式调用需要反射调用的方法(或者属性.字段),而不去使用Invoke方法) 创建Delegate (1).Delegate.CreateDelegate(Type, ...
- Android开发环境内容汇总
Android开发环境将分为SDK相关内容.Eclipse ADT相关内容.模拟器AVD相关内容.调试器DDMS相关内容.日志LogCat相关内容.连接驱动ADB相关内容.内存泄露检测工具MAT相关 ...
- Android开发环境——模拟器AVD相关内容汇总
Android开发环境将分为SDK相关内容.Eclipse ADT相关内容.模拟器AVD相关内容.调试器DDMS相关内容.日志LogCat相关内容.连接驱动ADB相关内容.内存泄露检测工具MAT相关 ...
- Android开发环境——Eclipse ADT相关内容汇总
Android开发环境将分为SDK相关内容.Eclipse ADT相关内容.模拟器AVD相关内容.调试器DDMS相关内容.日志LogCat相关内容.连接驱动ADB相关内容.内存泄露检测工具MAT相关 ...
- Mysql查询优化汇总 order by优化例子,group by优化例子,limit优化例子,优化建议
Mysql查询优化汇总 order by优化例子,group by优化例子,limit优化例子,优化建议 索引 索引是一种存储引擎快速查询记录的一种数据结构. 注意 MYSQL一次查询只能使用一个索引 ...
- 在xadmin中自定义内容的变量及优化汇总
在网上找了很多有关xadmin的内容,发现都不太全 ,找到一篇总结不错的 http://www.lybbn.cn/data/bbsdatas.php?lybbs=62 1.list_display 指 ...
- 使用Java反射优化多个方法调用
有段时间没来写博客了,心里一直念叨空了来,今天有时间来记录一篇.前段时间领导提出优化部分系统模块,根据业务要求系统中有很多产品,产品下面有N个指标,一个指标就对应一个方法,所以系统代码中就是这样一个情 ...
- 快速傅里叶变换(FFT)相关内容汇总
(原稿:https://paste.ubuntu.com/p/yJNsn3xPt8/) 快速傅里叶变换,是求两个多项式卷积的算法,其时间复杂度为$O(n\log n)$,优于普通卷积求法,且根据有关证 ...
- 用简单的反射优化代码(动态web项目)
在动态web项目中,没有使用框架时,只是简单的jsp访问servlet实现增删改查, 无论是哪个方法都需要经过Servlet中的doGet()方法或doPost()方法,我们可以在链接中附带参数进行区 ...
随机推荐
- NC20583 [SDOI2016]齿轮
题目链接 题目 题目描述 现有一个传动系统,包含了N个组合齿轮和M个链条.每一个链条连接了两个组合齿轮u和v,并提供了一个传动比x : y. 即如果只考虑这两个组合齿轮,编号为u的齿轮转动x圈,编号为 ...
- 小红书携手HMS Core,畅玩高清视界,种草美好生活
在相同流量消耗的情况下,540p可秒变1080p?这不是魔法,通过视频超分辨率技术(简称视频超分),就能让视频变得更清晰. 7月20日,在小红书最新版本7.48的App中,用户就能体验到这项技术带来的 ...
- mysql导出bug备注
注:yiicms库和area表均存在
- Vue路由器的hash和history两种工作模式 && Vue项目编译部署
1 # 一.Vue路由器的两种工作模式 2 # 1.对于一个uri来说,什么是hash值? 井号及其后面的内容就是hash值. 3 # 2.hash值不会包括含在HTTP请求中,即:hash值不会带给 ...
- MySQL金融应用场景下跨数据中心的MGR架构方案(1)
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 0. 内容提纲 运行环境 部署MGR A&B 部署MGR A.B之间的复制通道 几个注意事项 如何在多个数据中心部 ...
- BMP位图之1位位图(一)
起始结构 typedef struct tagBITMAPFILEHEADER { WORD bfType; //类型名,字符串"BM", DWORD bfSize; //文件大小 ...
- react学习1-jsx语法注意点
* 1.定义虚拟DOM不要写引号 * 2.标签中使用js表达式的时候,要使用{} * 3.样式类名指定要使用className * 4.要使用内联样式的话,要使用style={{key:"v ...
- 八个解决你80%需求的CSS动画库
八个解决你80%需求的CSS动画库 点击打开视频讲解 在学习和工作的过程中,我们总免不了要写各种各样的css动画,给某个部分添加动画效果,如果觉得自己写的动画效果单一乏味,不妨试试这8个CSS动画库, ...
- 一文搞懂│mysql 中的备份恢复、分区分表、主从复制、读写分离
目录 mysql 的备份和恢复 mysql 的分区分表 mysql 的主从复制读写分离 mysql 的备份和恢复 创建备份管理员 创建备份管理员,并授予管理员相应的权限 备份所需权限:select,r ...
- 微软Azure配置中心 App Configuration (三):配置的动态更新
写在前面 我在前文: <微软Azure配置中心 App Configuration (一):轻松集成到Asp.Net Core>已经介绍了Asp.net Core怎么轻易的接入azure ...