寻找性能更优秀的动态 Getter 和 Setter 方案

反射获取 PropertyInfo 可以对对象的属性值进行读取或者写入,但是这样性能不好。所以,我们需要更快的方案。

方案说明

就是用表达式编译一个Action<TObj,TValue>作为 Setter,编译一个Func<TObj,TValue>作为 Getter。

然后把这些编译好的委托放在一个泛型类的静态字段中保存起来,需要使用的时候从这里面查找就可以了。

知识要点

  1. 使用表达式创建委托

  2. 泛型类的静态字段是每个闭合类型独立的,因此用于存储和类型相关的内容非常方便

实现代码

由于代码中混合的使用 Switch 作为字典的阴招,所以代码很长,此处不再罗列,仅给出链接:

  • - [Github ValueGetter](https://github.com/newbe36524/Newbe.ObjectVisitor/blob/main/src/Newbe.ObjectVisitor/Newbe.ObjectVisitor/Core/ValueGetter.cs)

  • - [Github ValueSetter](https://github.com/newbe36524/Newbe.ObjectVisitor/blob/main/src/Newbe.ObjectVisitor/Newbe.ObjectVisitor/Core/ValueSetter.cs)

  • - [Gitee ValueGetter](https://gitee.com/yks/Newbe.ObjectVisitor/blob/main/src/Newbe.ObjectVisitor/Newbe.ObjectVisitor/Core/ValueGetter.cs)

  • - [Gitee ValueSetter](https://gitee.com/yks/Newbe.ObjectVisitor/blob/main/src/Newbe.ObjectVisitor/Newbe.ObjectVisitor/Core/ValueSetter.cs)

基准测试


BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19041.572 (2004/?/20H1)
Intel Xeon CPU E5-2678 v3 2.50GHz, 1 CPU, 24 logical and 12 physical cores
.NET Core SDK=5.0.100-rc.2.20479.15[Host]       : .NET Core 2.1.23 (CoreCLR 4.6.29321.03, CoreFX 4.6.29321.01), X64 RyuJITnet461       : .NET Framework 4.8 (4.8.4250.0), X64 RyuJITnet48        : .NET Framework 4.8 (4.8.4250.0), X64 RyuJITnetcoreapp21 : .NET Core 2.1.23 (CoreCLR 4.6.29321.03, CoreFX 4.6.29321.01), X64 RyuJITnetcoreapp31 : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJITnetcoreapp5  : .NET Core 5.0.0 (CoreCLR 5.0.20.47505, CoreFX 5.0.20.47505), X64 RyuJIT

结论

  1. 使用委托明显比使用 PropertyInfo 要快,这个方案可以。

  2. Framework 真拉胯,Net 5 简直太强了。

  3. 如果属性是明确的,建议把字典中取出来的委托保存在自己的上下文,这可以明显的省去查找的消耗。

图表

从左往右分别是:直接读取属性、缓存委托、不缓存委托和使用 PropertyInfo。

数据

Getter

MethodJobRuntimeMeanErrorStdDevMedianRatioRatioSDRank
DirectlyStringnet461.NET 4.6.10.1636 ns0.0822 ns0.1126 ns0.1472 ns??2
DirectlyIntnet461.NET 4.6.10.0318 ns0.0348 ns0.0342 ns0.0217 ns??1
ReflectStringnet461.NET 4.6.1145.8375 ns2.2790 ns2.1317 ns145.6522 ns??7
ReflectIntnet461.NET 4.6.1172.5066 ns1.3206 ns1.1028 ns172.6804 ns??8
GetterStringnet461.NET 4.6.131.4379 ns0.6017 ns0.5334 ns31.6316 ns??4
GetterIntnet461.NET 4.6.133.0642 ns0.4940 ns0.4380 ns33.0557 ns??5
GetterObjectnet461.NET 4.6.133.9174 ns0.5587 ns0.5226 ns33.7326 ns??6
GetterCachednet461.NET 4.6.17.5878 ns0.1223 ns0.1144 ns7.5765 ns??3










DirectlyStringnet48.NET 4.80.0181 ns0.0353 ns0.0313 ns0.0043 ns??1
DirectlyIntnet48.NET 4.80.0050 ns0.0089 ns0.0079 ns0.0000 ns??1
ReflectStringnet48.NET 4.8143.8313 ns2.2501 ns2.1047 ns143.5568 ns??5
ReflectIntnet48.NET 4.8172.1714 ns1.9819 ns1.7569 ns172.3142 ns??6
GetterStringnet48.NET 4.831.5887 ns0.6310 ns0.5902 ns31.5385 ns??3
GetterIntnet48.NET 4.832.7140 ns0.3992 ns0.3734 ns32.7343 ns??4
GetterObjectnet48.NET 4.833.3063 ns0.2069 ns0.1834 ns33.3053 ns??4
GetterCachednet48.NET 4.87.5540 ns0.2201 ns0.1951 ns7.5069 ns??2










DirectlyStringnetcoreapp21.NET Core 2.10.0000 ns0.0000 ns0.0000 ns0.0000 ns??1
DirectlyIntnetcoreapp21.NET Core 2.10.0193 ns0.0111 ns0.0104 ns0.0177 ns??2
ReflectStringnetcoreapp21.NET Core 2.1110.4180 ns2.2159 ns1.8503 ns110.8038 ns??7
ReflectIntnetcoreapp21.NET Core 2.1138.9612 ns0.9694 ns0.8594 ns138.8217 ns??8
GetterStringnetcoreapp21.NET Core 2.116.8958 ns0.2384 ns0.2230 ns16.8103 ns??4
GetterIntnetcoreapp21.NET Core 2.119.4407 ns0.2041 ns0.1809 ns19.4539 ns??6
GetterObjectnetcoreapp21.NET Core 2.118.6922 ns0.2700 ns0.2255 ns18.6582 ns??5
GetterCachednetcoreapp21.NET Core 2.10.9299 ns0.0457 ns0.0427 ns0.9308 ns??3










DirectlyStringnetcoreapp31.NET Core 3.10.0000 ns0.0000 ns0.0000 ns0.0000 ns??1
DirectlyIntnetcoreapp31.NET Core 3.10.0693 ns0.0102 ns0.0091 ns0.0709 ns??2
ReflectStringnetcoreapp31.NET Core 3.198.6735 ns0.8335 ns0.7389 ns98.5319 ns??7
ReflectIntnetcoreapp31.NET Core 3.1130.6941 ns0.9332 ns0.8730 ns130.5376 ns??8
GetterStringnetcoreapp31.NET Core 3.114.8915 ns0.2025 ns0.1795 ns14.8911 ns??4
GetterIntnetcoreapp31.NET Core 3.116.2874 ns0.0789 ns0.0700 ns16.2753 ns??5
GetterObjectnetcoreapp31.NET Core 3.117.6202 ns0.1130 ns0.1057 ns17.6092 ns??6
GetterCachednetcoreapp31.NET Core 3.10.6351 ns0.0244 ns0.0217 ns0.6393 ns??3










DirectlyStringnetcoreapp5.NET Core 5.00.5098 ns0.0328 ns0.0291 ns0.5131 ns1.0000.002
DirectlyIntnetcoreapp5.NET Core 5.00.0000 ns0.0000 ns0.0000 ns0.0000 ns0.0000.001
ReflectStringnetcoreapp5.NET Core 5.088.8937 ns0.9697 ns0.8596 ns88.7457 ns174.8389.267
ReflectIntnetcoreapp5.NET Core 5.0123.4464 ns1.0582 ns0.9898 ns123.3193 ns242.99614.008
GetterStringnetcoreapp5.NET Core 5.07.6628 ns0.0931 ns0.0777 ns7.6703 ns15.0310.955
GetterIntnetcoreapp5.NET Core 5.06.6645 ns0.0825 ns0.0772 ns6.6497 ns13.0850.694
GetterObjectnetcoreapp5.NET Core 5.08.3090 ns0.1685 ns0.1576 ns8.2865 ns16.3440.836
GetterCachednetcoreapp5.NET Core 5.00.9791 ns0.0293 ns0.0245 ns0.9764 ns1.9200.133

Setter

MethodJobRuntimeMeanErrorStdDevMedianRatioRatioSDRank
DirectlyStringnet461.NET 4.6.12.0161 ns0.0300 ns0.0266 ns2.0045 ns1.0000.002
DirectlyIntnet461.NET 4.6.10.0076 ns0.0094 ns0.0083 ns0.0081 ns0.0040.001
ReflectStringnet461.NET 4.6.1237.5006 ns4.5706 ns4.4890 ns236.5912 ns117.8713.405
ReflectIntnet461.NET 4.6.1249.3627 ns2.1717 ns2.0314 ns249.0283 ns123.6811.946
GetterStringnet461.NET 4.6.132.8621 ns0.2855 ns0.2229 ns32.9189 ns16.3350.224
GetterIntnet461.NET 4.6.133.6103 ns0.4245 ns0.3544 ns33.5499 ns16.6950.264
GetterObjectnet461.NET 4.6.133.2561 ns0.2966 ns0.2629 ns33.1795 ns16.4970.174
GetterCachednet461.NET 4.6.19.1805 ns0.0761 ns0.0674 ns9.1802 ns4.5540.083










DirectlyStringnet48.NET 4.81.9272 ns0.0298 ns0.0264 ns1.9245 ns1.0000.002
DirectlyIntnet48.NET 4.80.0000 ns0.0000 ns0.0000 ns0.0000 ns0.0000.001
ReflectStringnet48.NET 4.8237.7686 ns4.6597 ns5.3661 ns235.8445 ns123.9083.575
ReflectIntnet48.NET 4.8249.6291 ns4.5333 ns4.2404 ns249.5459 ns129.6893.136
GetterStringnet48.NET 4.832.2366 ns0.1941 ns0.1721 ns32.1780 ns16.7310.294
GetterIntnet48.NET 4.832.0081 ns0.1488 ns0.1162 ns32.0270 ns16.5720.234
GetterObjectnet48.NET 4.832.6413 ns0.1417 ns0.1183 ns32.6260 ns16.9070.244
GetterCachednet48.NET 4.89.2589 ns0.0928 ns0.0868 ns9.2564 ns4.7990.073










DirectlyStringnetcoreapp21.NET Core 2.12.4107 ns0.0507 ns0.0475 ns2.3936 ns1.0000.002
DirectlyIntnetcoreapp21.NET Core 2.10.0007 ns0.0028 ns0.0025 ns0.0000 ns0.0000.001
ReflectStringnetcoreapp21.NET Core 2.1203.6637 ns3.6109 ns3.3777 ns203.4793 ns84.5172.317
ReflectIntnetcoreapp21.NET Core 2.1213.8619 ns2.1882 ns1.9398 ns213.7367 ns88.7571.718
GetterStringnetcoreapp21.NET Core 2.119.5240 ns0.0811 ns0.0758 ns19.5149 ns8.1020.155
GetterIntnetcoreapp21.NET Core 2.118.8794 ns0.1193 ns0.1058 ns18.8837 ns7.8360.184
GetterObjectnetcoreapp21.NET Core 2.120.6765 ns0.2709 ns0.2115 ns20.6419 ns8.5840.146
GetterCachednetcoreapp21.NET Core 2.12.7606 ns0.0613 ns0.0512 ns2.7590 ns1.1480.023










DirectlyStringnetcoreapp31.NET Core 3.12.2625 ns0.0647 ns0.0605 ns2.2555 ns1.0000.002
DirectlyIntnetcoreapp31.NET Core 3.10.0072 ns0.0165 ns0.0146 ns0.0000 ns0.0030.011
ReflectStringnetcoreapp31.NET Core 3.1182.7306 ns3.3249 ns3.1101 ns182.3062 ns80.8041.997
ReflectIntnetcoreapp31.NET Core 3.1192.2510 ns2.3691 ns2.1002 ns191.4821 ns85.0612.888
GetterStringnetcoreapp31.NET Core 3.116.9918 ns0.2115 ns0.1979 ns16.9651 ns7.5160.255
GetterIntnetcoreapp31.NET Core 3.116.1168 ns0.3558 ns0.3654 ns15.9822 ns7.1380.194
GetterObjectnetcoreapp31.NET Core 3.119.3060 ns0.4173 ns0.5571 ns19.4856 ns8.4800.456
GetterCachednetcoreapp31.NET Core 3.12.9276 ns0.0156 ns0.0146 ns2.9313 ns1.2950.033










DirectlyStringnetcoreapp5.NET Core 5.02.2455 ns0.0084 ns0.0078 ns2.2460 ns1.0000.002
DirectlyIntnetcoreapp5.NET Core 5.00.0000 ns0.0000 ns0.0000 ns0.0000 ns0.0000.001
ReflectStringnetcoreapp5.NET Core 5.0162.8780 ns0.7135 ns0.6674 ns162.8741 ns72.5380.457
ReflectIntnetcoreapp5.NET Core 5.0171.1380 ns0.4173 ns0.3699 ns171.1414 ns76.2170.318
GetterStringnetcoreapp5.NET Core 5.08.6244 ns0.1891 ns0.1769 ns8.5469 ns3.8410.085
GetterIntnetcoreapp5.NET Core 5.06.5511 ns0.0347 ns0.0325 ns6.5634 ns2.9170.024
GetterObjectnetcoreapp5.NET Core 5.09.0732 ns0.0306 ns0.0272 ns9.0735 ns4.0410.026
GetterCachednetcoreapp5.NET Core 5.02.8223 ns0.0728 ns0.0681 ns2.8190 ns1.2570.033

总结

使用表达式创建委托来取代 PropertyInfo 读取和写入属性效果很好。

开发者也可以直接引用 Newbe.ObjectVisitor 包来使用已经封装好的 ValueGetter 和 ValueSetter。

我只是知识的搬运工

- [晚绑定场景下对象属性赋值和取值可以不需要 PropertyInfo](https://www.cnblogs.com/artech/archive/2011/03/24/PropertyAccessor.html)

- [三种属性操作性能比较:PropertyInfo + Expression Tree + Delegate.CreateDelegate](https://www.cnblogs.com/artech/archive/2011/03/26/Propertyaccesstest.html)

- [关于 Expression Tree 和 IL Emit 的所谓的"性能差别"](https://www.cnblogs.com/artech/archive/2011/03/27/ExpressTreeVsIlEmit.html)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/307016.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Newbe.ObjectVisitor 0.2.10 发布,更花里胡哨

更新内容 现在&#xff0c;你可以通过上下文修改属性的值了&#xff1a;//✔️ from 0.2 // 可以修改属性 o.V().ForEach((context) > ModifyData(context)).Run();public static void ModifyData(IObjectVisitorContext<Yueluo,string> context) {context.Value con…

.NET 5 和 C#9 /F#5 一起到来, 向实现 .NET 统一迈出了一大步

经过一年多的开发&#xff0c;Microsoft 于北京时间 11 月 11 日&#xff08;星期三&#xff09;发布了其 .NET 5软件开发平台&#xff0c;强调平台的统一&#xff0c;并引入了 C# 9 和 F# 5 编程语言&#xff0c;新平台朝着桌面、Web、移动、云和 IoT 目标统一 .NET 开发体验的…

.NetCore HttpClient发送请求的时候为什么自动带上了一个RequestId头部?

奇怪的问题最近在公司有个系统需要调用第三方的一个webservice。本来调用一个下很简单的事情&#xff0c;使用HttpClient构造一个SOAP请求发送出去拿到XML解析就是了。可奇怪的是我们的请求在运行一段时间后就会被服务器504给拒绝掉了。导致系统无法使用&#xff0c;用户叫苦连…

ASP.NETCore小技巧:使用测试用户中间件

哈喽大家好&#xff0c;这篇文章其实很早就想写了&#xff0c;因为一直会有小伙伴问到&#xff0c;但是我却始终拿不到好的方案&#xff0c;最近在录制《eShopOnContainer微服务架构》的视频&#xff0c;碰巧就看到了微软官方的代码中也有这方面的需求&#xff0c;而且和我的需…

【招聘(深圳)】华强方特文化科技集团 .NET工程师

.NET高级开发工程师&#xff08;18-25K&#xff09;岗位职责&#xff1a;负责系统需求分析与设计&#xff1b;根据业务确定实现方案&#xff1b;对现有系统缺陷提出优化方案&#xff1b;负责系统关键功能开发及维护&#xff0c;保障系统的正常运行&#xff1b;带领指导团队开发…

11座城市,58个.NET最新岗位速览,内推直通面试官!

十一月风雪客&#xff0c;十二月乘衣归&#xff01;各个大厂秋招进行时&#xff0c;你行动了吗&#xff1f;借着这阵风&#xff0c;今天为大家提供一批.NET开发岗位内推&#xff01;58个优质的.NET开发岗位年薪过万到百万不等&#xff0c;总有一个适合你&#xff01;包含全国各…

pdo mysql_PDO MySQL

PDO MySQL如果文章有成千上万篇&#xff0c;该怎样保存&#xff1f;数据保存有多种方式&#xff0c;比如单机文件、单机数据库(SQLite)、网络数据库(MySQL、MariaDB)等等。根据项目来选择&#xff0c;做Web一般采用MySQL&#xff0c;本书也以MySQL为例。自学&#xff1a;1天。假…

C# 8: 可变结构体中的只读实例成员

在之前的文章中我们介绍了 C# 中的 只读结构体&#xff08;readonly struct&#xff09;[1] 和与其紧密相关的 in 参数[2]。今天我们来讨论一下从 C# 8 开始引入的一个特性&#xff1a;可变结构体中的只读实例成员&#xff08;当结构体可变时&#xff0c;将不会改变结构体状态的…

部署Dotnet Core应用到Kubernetes(一)

最近闲了点&#xff0c;写个大活&#xff1a;部署Dotnet应用到K8s。写在前边的话一直想完成这个主题。但这个主题实在太大了&#xff0c;各种拖延症的小宇宙不时爆发一下&#xff0c;结果就拖到了现在。这个主题&#xff0c;会是一个系列。在这个系列中&#xff0c;我会讨论将应…

JAVA实验报告九异常处理_Java课后练习9(异常处理)

动手动脑1:import javax.swing.*;class AboutException {public static void main(String[] a){int i1, j0, k;ki/j;try{k i/j; // Causes division-by-zero exception//throw new Exception("Hello.Exception!");}catch ( ArithmeticException e){System.out.print…

java 实现 指派_TAP任务指派问题的汇编实现

近六周的课程设计&#xff0c;编了一个四百行的汇编程序&#xff0c;编的过程很不顺利&#xff0c;遇到种种意想不到的困难&#xff0c;但最终能够实现&#xff0c;可谓欣喜若狂&#xff0c;这期间学到了好多好多&#xff0c;遇到问题怎么精下心来解决&#xff0c;同时对汇编的…

.NET 5.0正式发布,有什么功能特性(翻译)

我们很高兴今天.NET5.0正式发布。这是一个重要的版本—其中也包括了C# 9和F# 5大量新特性和优秀的改进。微软和其他公司的团队已经在生产和性能测试环境中开始使用了。这些团队向我们反馈的结果比较令人满意&#xff0c;它证明了对性能提升及降低Web应用托管成本的机会有积极的…

简单聊聊C#中lock关键字

为了避免多个线程同时操作同一资源&#xff0c;引起数据错误&#xff0c;通常我们会将这个资源加上锁&#xff0c;这样在同一时间只能有一个线程操作资源。在C#中我们使用lock关键字来锁定资源&#xff0c;那lock关键字是如何实现锁定的呢&#xff1f;我们先看一段代码&#xf…

idea如何导入java工程_Eclipse java web项目 ,导入IntelliJ IDEA 完整操作!

或许你用惯了Eclipse&#xff0c;有点排斥其他工具了&#xff0c;你写框架的时候&#xff0c;编译速度是不是特别慢啊&#xff1f;有时候还超过45秒&#xff0c;自动取消运行&#xff01;有时候代码是正常的&#xff0c;却无端端报错&#xff1f;下午吃个饭回来又好了&#xff…

行业思考 | 互联网对传统行业的降维打击

【行业思考】| 作者 / Edison Zhou这是EdisonTalk的第301篇原创内容在周一发布的推文《我在传统行业做数字化转型之预告篇》中&#xff0c;我提到互联网的发展和和竞争对传统行业起到了降维打击的作用&#xff0c;于是就有童鞋私下问我&#xff0c;为何这么说。今天就跟你聊聊这…

BCVP开发者说第一期:Destiny.Core.Flow

沉静岁月&#xff0c;淡忘流年1项目简介Destiny.Core.FlowDestiny.Core.Flow是基于.NetCore平台&#xff0c;轻量级的模块化开发框架&#xff0c;Admin管理应用框架&#xff0c;旨在提升团队的快速开发输出能力&#xff0c;由常用公共操作类&#xff08;工具类、帮助类&#xf…

.NET Core 取消令牌:CancellationToken

在 .NET 开发中&#xff0c;CancellationToken&#xff08;取消令牌&#xff09;是一项比较重要的功能&#xff0c;掌握并合理的使用 CancellationToken 可以提升服务的性能。特别在异步编程中&#xff0c;我常常会以创建 Task 的方式利用多线程执行一些耗时或非核心业务逻辑&a…

java char short区别_java 彻底理解 byte char short int float long double

遇到过很多关于 数值类型范围的问题了&#xff0c;在这做一个总结&#xff0c;我们可以从多方面理解不同数值类型的所能表示的数值范围在这里我们只谈论 java中的数值类型首先说byte&#xff1a;这段是摘自jdk中 Byte.java中的源代码从这里可以看出 byte的取值范围&#xff1a;…

程序员过关斩将--从未停止过的系统架构设计步伐

“首先&#xff0c;这篇文章肯定会得罪一些人“其次&#xff0c;此文只代表我个人的意见&#xff0c;仅供参考从分层说起谈到系统架构的分层和系统领域边界的划分&#xff0c;每个架构师&#xff0c;每个技术经理&#xff0c;甚至每个程序员都有自己的一套想法。无论是怎么样的…

BCVP第2期:项目已完成升级.NET5.0

(是时候拿出来这种图了)1开心的锣鼓想必这两天最热闹的几个词语&#xff0c;就是c#9.0、.net5.0还有conf大会了吧&#xff0c;当然还有大一统。其实&#xff0c;早在2019年年中&#xff0c;就已经引入了.NET5.0了&#xff0c;然后从2020-03-16开始&#xff0c;就一直在说.NET5.…