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

方案说明

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

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

知识要点

  1. 使用表达式创建委托
  2. 泛型类的静态字段是每个闭合类型独立的,因此用于存储和类型相关的内容非常方便

实现代码

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

基准测试

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 RyuJIT
net461 : .NET Framework 4.8 (4.8.4250.0), X64 RyuJIT
net48 : .NET Framework 4.8 (4.8.4250.0), X64 RyuJIT
netcoreapp21 : .NET Core 2.1.23 (CoreCLR 4.6.29321.03, CoreFX 4.6.29321.01), X64 RyuJIT
netcoreapp31 : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT
netcoreapp5 : .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

Method Job Runtime Mean Error StdDev Median Ratio RatioSD Rank
DirectlyString net461 .NET 4.6.1 0.1636 ns 0.0822 ns 0.1126 ns 0.1472 ns ? ? 2
DirectlyInt net461 .NET 4.6.1 0.0318 ns 0.0348 ns 0.0342 ns 0.0217 ns ? ? 1
ReflectString net461 .NET 4.6.1 145.8375 ns 2.2790 ns 2.1317 ns 145.6522 ns ? ? 7
ReflectInt net461 .NET 4.6.1 172.5066 ns 1.3206 ns 1.1028 ns 172.6804 ns ? ? 8
GetterString net461 .NET 4.6.1 31.4379 ns 0.6017 ns 0.5334 ns 31.6316 ns ? ? 4
GetterInt net461 .NET 4.6.1 33.0642 ns 0.4940 ns 0.4380 ns 33.0557 ns ? ? 5
GetterObject net461 .NET 4.6.1 33.9174 ns 0.5587 ns 0.5226 ns 33.7326 ns ? ? 6
GetterCached net461 .NET 4.6.1 7.5878 ns 0.1223 ns 0.1144 ns 7.5765 ns ? ? 3
                   
DirectlyString net48 .NET 4.8 0.0181 ns 0.0353 ns 0.0313 ns 0.0043 ns ? ? 1
DirectlyInt net48 .NET 4.8 0.0050 ns 0.0089 ns 0.0079 ns 0.0000 ns ? ? 1
ReflectString net48 .NET 4.8 143.8313 ns 2.2501 ns 2.1047 ns 143.5568 ns ? ? 5
ReflectInt net48 .NET 4.8 172.1714 ns 1.9819 ns 1.7569 ns 172.3142 ns ? ? 6
GetterString net48 .NET 4.8 31.5887 ns 0.6310 ns 0.5902 ns 31.5385 ns ? ? 3
GetterInt net48 .NET 4.8 32.7140 ns 0.3992 ns 0.3734 ns 32.7343 ns ? ? 4
GetterObject net48 .NET 4.8 33.3063 ns 0.2069 ns 0.1834 ns 33.3053 ns ? ? 4
GetterCached net48 .NET 4.8 7.5540 ns 0.2201 ns 0.1951 ns 7.5069 ns ? ? 2
                   
DirectlyString netcoreapp21 .NET Core 2.1 0.0000 ns 0.0000 ns 0.0000 ns 0.0000 ns ? ? 1
DirectlyInt netcoreapp21 .NET Core 2.1 0.0193 ns 0.0111 ns 0.0104 ns 0.0177 ns ? ? 2
ReflectString netcoreapp21 .NET Core 2.1 110.4180 ns 2.2159 ns 1.8503 ns 110.8038 ns ? ? 7
ReflectInt netcoreapp21 .NET Core 2.1 138.9612 ns 0.9694 ns 0.8594 ns 138.8217 ns ? ? 8
GetterString netcoreapp21 .NET Core 2.1 16.8958 ns 0.2384 ns 0.2230 ns 16.8103 ns ? ? 4
GetterInt netcoreapp21 .NET Core 2.1 19.4407 ns 0.2041 ns 0.1809 ns 19.4539 ns ? ? 6
GetterObject netcoreapp21 .NET Core 2.1 18.6922 ns 0.2700 ns 0.2255 ns 18.6582 ns ? ? 5
GetterCached netcoreapp21 .NET Core 2.1 0.9299 ns 0.0457 ns 0.0427 ns 0.9308 ns ? ? 3
                   
DirectlyString netcoreapp31 .NET Core 3.1 0.0000 ns 0.0000 ns 0.0000 ns 0.0000 ns ? ? 1
DirectlyInt netcoreapp31 .NET Core 3.1 0.0693 ns 0.0102 ns 0.0091 ns 0.0709 ns ? ? 2
ReflectString netcoreapp31 .NET Core 3.1 98.6735 ns 0.8335 ns 0.7389 ns 98.5319 ns ? ? 7
ReflectInt netcoreapp31 .NET Core 3.1 130.6941 ns 0.9332 ns 0.8730 ns 130.5376 ns ? ? 8
GetterString netcoreapp31 .NET Core 3.1 14.8915 ns 0.2025 ns 0.1795 ns 14.8911 ns ? ? 4
GetterInt netcoreapp31 .NET Core 3.1 16.2874 ns 0.0789 ns 0.0700 ns 16.2753 ns ? ? 5
GetterObject netcoreapp31 .NET Core 3.1 17.6202 ns 0.1130 ns 0.1057 ns 17.6092 ns ? ? 6
GetterCached netcoreapp31 .NET Core 3.1 0.6351 ns 0.0244 ns 0.0217 ns 0.6393 ns ? ? 3
                   
DirectlyString netcoreapp5 .NET Core 5.0 0.5098 ns 0.0328 ns 0.0291 ns 0.5131 ns 1.000 0.00 2
DirectlyInt netcoreapp5 .NET Core 5.0 0.0000 ns 0.0000 ns 0.0000 ns 0.0000 ns 0.000 0.00 1
ReflectString netcoreapp5 .NET Core 5.0 88.8937 ns 0.9697 ns 0.8596 ns 88.7457 ns 174.838 9.26 7
ReflectInt netcoreapp5 .NET Core 5.0 123.4464 ns 1.0582 ns 0.9898 ns 123.3193 ns 242.996 14.00 8
GetterString netcoreapp5 .NET Core 5.0 7.6628 ns 0.0931 ns 0.0777 ns 7.6703 ns 15.031 0.95 5
GetterInt netcoreapp5 .NET Core 5.0 6.6645 ns 0.0825 ns 0.0772 ns 6.6497 ns 13.085 0.69 4
GetterObject netcoreapp5 .NET Core 5.0 8.3090 ns 0.1685 ns 0.1576 ns 8.2865 ns 16.344 0.83 6
GetterCached netcoreapp5 .NET Core 5.0 0.9791 ns 0.0293 ns 0.0245 ns 0.9764 ns 1.920 0.13 3

Setter

Method Job Runtime Mean Error StdDev Median Ratio RatioSD Rank
DirectlyString net461 .NET 4.6.1 2.0161 ns 0.0300 ns 0.0266 ns 2.0045 ns 1.000 0.00 2
DirectlyInt net461 .NET 4.6.1 0.0076 ns 0.0094 ns 0.0083 ns 0.0081 ns 0.004 0.00 1
ReflectString net461 .NET 4.6.1 237.5006 ns 4.5706 ns 4.4890 ns 236.5912 ns 117.871 3.40 5
ReflectInt net461 .NET 4.6.1 249.3627 ns 2.1717 ns 2.0314 ns 249.0283 ns 123.681 1.94 6
GetterString net461 .NET 4.6.1 32.8621 ns 0.2855 ns 0.2229 ns 32.9189 ns 16.335 0.22 4
GetterInt net461 .NET 4.6.1 33.6103 ns 0.4245 ns 0.3544 ns 33.5499 ns 16.695 0.26 4
GetterObject net461 .NET 4.6.1 33.2561 ns 0.2966 ns 0.2629 ns 33.1795 ns 16.497 0.17 4
GetterCached net461 .NET 4.6.1 9.1805 ns 0.0761 ns 0.0674 ns 9.1802 ns 4.554 0.08 3
                   
DirectlyString net48 .NET 4.8 1.9272 ns 0.0298 ns 0.0264 ns 1.9245 ns 1.000 0.00 2
DirectlyInt net48 .NET 4.8 0.0000 ns 0.0000 ns 0.0000 ns 0.0000 ns 0.000 0.00 1
ReflectString net48 .NET 4.8 237.7686 ns 4.6597 ns 5.3661 ns 235.8445 ns 123.908 3.57 5
ReflectInt net48 .NET 4.8 249.6291 ns 4.5333 ns 4.2404 ns 249.5459 ns 129.689 3.13 6
GetterString net48 .NET 4.8 32.2366 ns 0.1941 ns 0.1721 ns 32.1780 ns 16.731 0.29 4
GetterInt net48 .NET 4.8 32.0081 ns 0.1488 ns 0.1162 ns 32.0270 ns 16.572 0.23 4
GetterObject net48 .NET 4.8 32.6413 ns 0.1417 ns 0.1183 ns 32.6260 ns 16.907 0.24 4
GetterCached net48 .NET 4.8 9.2589 ns 0.0928 ns 0.0868 ns 9.2564 ns 4.799 0.07 3
                   
DirectlyString netcoreapp21 .NET Core 2.1 2.4107 ns 0.0507 ns 0.0475 ns 2.3936 ns 1.000 0.00 2
DirectlyInt netcoreapp21 .NET Core 2.1 0.0007 ns 0.0028 ns 0.0025 ns 0.0000 ns 0.000 0.00 1
ReflectString netcoreapp21 .NET Core 2.1 203.6637 ns 3.6109 ns 3.3777 ns 203.4793 ns 84.517 2.31 7
ReflectInt netcoreapp21 .NET Core 2.1 213.8619 ns 2.1882 ns 1.9398 ns 213.7367 ns 88.757 1.71 8
GetterString netcoreapp21 .NET Core 2.1 19.5240 ns 0.0811 ns 0.0758 ns 19.5149 ns 8.102 0.15 5
GetterInt netcoreapp21 .NET Core 2.1 18.8794 ns 0.1193 ns 0.1058 ns 18.8837 ns 7.836 0.18 4
GetterObject netcoreapp21 .NET Core 2.1 20.6765 ns 0.2709 ns 0.2115 ns 20.6419 ns 8.584 0.14 6
GetterCached netcoreapp21 .NET Core 2.1 2.7606 ns 0.0613 ns 0.0512 ns 2.7590 ns 1.148 0.02 3
                   
DirectlyString netcoreapp31 .NET Core 3.1 2.2625 ns 0.0647 ns 0.0605 ns 2.2555 ns 1.000 0.00 2
DirectlyInt netcoreapp31 .NET Core 3.1 0.0072 ns 0.0165 ns 0.0146 ns 0.0000 ns 0.003 0.01 1
ReflectString netcoreapp31 .NET Core 3.1 182.7306 ns 3.3249 ns 3.1101 ns 182.3062 ns 80.804 1.99 7
ReflectInt netcoreapp31 .NET Core 3.1 192.2510 ns 2.3691 ns 2.1002 ns 191.4821 ns 85.061 2.88 8
GetterString netcoreapp31 .NET Core 3.1 16.9918 ns 0.2115 ns 0.1979 ns 16.9651 ns 7.516 0.25 5
GetterInt netcoreapp31 .NET Core 3.1 16.1168 ns 0.3558 ns 0.3654 ns 15.9822 ns 7.138 0.19 4
GetterObject netcoreapp31 .NET Core 3.1 19.3060 ns 0.4173 ns 0.5571 ns 19.4856 ns 8.480 0.45 6
GetterCached netcoreapp31 .NET Core 3.1 2.9276 ns 0.0156 ns 0.0146 ns 2.9313 ns 1.295 0.03 3
                   
DirectlyString netcoreapp5 .NET Core 5.0 2.2455 ns 0.0084 ns 0.0078 ns 2.2460 ns 1.000 0.00 2
DirectlyInt netcoreapp5 .NET Core 5.0 0.0000 ns 0.0000 ns 0.0000 ns 0.0000 ns 0.000 0.00 1
ReflectString netcoreapp5 .NET Core 5.0 162.8780 ns 0.7135 ns 0.6674 ns 162.8741 ns 72.538 0.45 7
ReflectInt netcoreapp5 .NET Core 5.0 171.1380 ns 0.4173 ns 0.3699 ns 171.1414 ns 76.217 0.31 8
GetterString netcoreapp5 .NET Core 5.0 8.6244 ns 0.1891 ns 0.1769 ns 8.5469 ns 3.841 0.08 5
GetterInt netcoreapp5 .NET Core 5.0 6.5511 ns 0.0347 ns 0.0325 ns 6.5634 ns 2.917 0.02 4
GetterObject netcoreapp5 .NET Core 5.0 9.0732 ns 0.0306 ns 0.0272 ns 9.0735 ns 4.041 0.02 6
GetterCached netcoreapp5 .NET Core 5.0 2.8223 ns 0.0728 ns 0.0681 ns 2.8190 ns 1.257 0.03 3

总结

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

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

我只是知识的搬运工

发布说明

使用样例

番外分享

GitHub 项目地址:https://github.com/newbe36524/Newbe.ObjectVisitor

Gitee 项目地址:https://gitee.com/yks/Newbe.ObjectVisitor

寻找性能更优秀的动态 Getter 和 Setter 方案的更多相关文章

  1. Stylus-NodeJS下构建更富表现力/动态/健壮的CSS

    --------------------------本文来自张鑫旭大神博客------------------------------ 一.为什么我会讲Stylus,而不是SASS和LESS? SAS ...

  2. 比Kafka Mangaer更优秀的开源监控工具-Kafka Eagle

    比Kafka Mangaer更优秀的开源监控工具-Kafka Eagle 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在Kafka的监控系统中有很多优秀的开源监控系统.比如Kaf ...

  3. 通过AI自学习,Google让Pixel 3的人像模式更优秀

    通过AI自学习,Google让Pixel 3的人像模式更优秀 Link: https://news.cnblogs.com/n/613720/ 虽然双摄手机已经在市场上普及,其所带来的人像模式.多倍变 ...

  4. Qunar机票技术部就有一个全年很关键的一个指标:搜索缓存命中率,当时已经做到了>99.7%。再往后,每提高0.1%,优化难度成指数级增长了。哪怕是千分之一,也直接影响用户体验,影响每天上万张机票的销售额。 在高并发场景下,提供了保证线程安全的对象、方法。比如经典的ConcurrentHashMap,它比起HashMap,有更小粒度的锁,并发读写性能更好。线程安全的StringBuilder取代S

    Qunar机票技术部就有一个全年很关键的一个指标:搜索缓存命中率,当时已经做到了>99.7%.再往后,每提高0.1%,优化难度成指数级增长了.哪怕是千分之一,也直接影响用户体验,影响每天上万张机 ...

  5. Ember.js和Vue.js对比,哪个框架更优秀?

    本文由葡萄城技术团队于博客园翻译并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. JavaScript最初是为Web应用程序创建的.但是随着前端技术的 ...

  6. 异步IO比同步阻塞IO性能更好吗?为什么?

    最近在看node.js, 介绍中提到node是异步io的方式实现, 性能比同步阻塞io的更好. 对于一个request而言, 如果我们依赖io的结果, 异步io和同步阻塞io都是要等到io完成才能继续 ...

  7. PHP日志扩展 SeasLog-1.6.8, 性能更优

    SeasLog-1.6.8 发布了,性能更优. 改进日志: 1.6.8: 优化内存使用和性能,修复已知Bug. - Fixed issue #97 PHP5.* Cached Block. - Fix ...

  8. 能让你成为更优秀程序员的10个C语言资源

    能让你成为更优秀程序员的10个C语言资源 本文由 伯乐在线 - archychu 翻译自 mycplus.欢迎加入 技术翻译小组.转载请参见文章末尾处的要求. 一些人觉得编程无聊,一些人觉得它很好玩. ...

  9. graphicview和widgets没本质区别。它只是更轻量级,更灵活,性能更高的widgets

    graphicview和widgets没本质区别.它只是更轻量级,更灵活,性能更高的widgets.核心就是把widgets变成了更轻量级的graphicitem,把QWidget的各种事件转换成了g ...

随机推荐

  1. 007 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 01 Java标识符

    007 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 01 Java标识符 Java变量与常量主要内容 Java变量与常量主要内容如下,主要是对以下内容的学习,没 ...

  2. matlab receive License Manager Error -103?

    参考:https://www.mathworks.com/matlabcentral/answers/91874-why-do-i-receive-license-manager-error-103 ...

  3. k8s的namespace一直Terminating的完美解决方案

    k8s的namespace一直Terminating的完美解决方案 在k8s集群中进行测试删除namespace是经常的事件,而为了方便操作,一般都是直接对整个名称空间进行删除操作. 相信道友们在进行 ...

  4. java高级项目 jdbc与数据库连接数据库

    //图书管类 public class Book { private Integer id; private String b_name; private double b_price; privat ...

  5. ConcurrentHashMap源码解析,多线程扩容

    前面一篇已经介绍过了 HashMap 的源码: HashMap源码解析.jdk7和8之后的区别.相关问题分析 HashMap并不是线程安全的,他就一个普通的容器,没有做相关的同步处理,因此线程不安全主 ...

  6. centos7 yum 安装nodejs、npm、cnpm、pm2、yarn

    一.环境准备 1.1 查看系统环境 [root@localhost ~]# cat /etc/redhat-release CentOS Linux release 7.5.1804 (Core) [ ...

  7. Fiddler抓包工具 请求图标为一个锁的图标的设置

    第一步,Fiddler抓包的数据 前面的都是一个锁的图标,的设置方法, 然后 点击打开 按此设置图一 在图二, 图三. 其他默认就好

  8. reids等非关系数据库管理工具treesoft

    先下载treesoft 链接:https://pan.baidu.com/s/1o8UPK7lF0-WvE9afoR0sWw 提取码:3uc3 下载好之后进行解压文件 解压完成后目录结构 将webap ...

  9. python -re库

    正则表达式的语法 正则表达式语法由字符和操作符构成 正则表达式的常用操作符: print("--正则表达式常用操作符--") mata="11356352135 abcd ...

  10. 如何从0到1的构建一款Java数据生成器-第一章

    前提 某天晚上老夫在神游时,想起白天公司同事说起的问题,这老表抱怨使用mysql生成大批的随机测试数据太过麻烦,问大家有没有好的工具推荐,老夫对这种事情当然不关心,毕竟我也不知道. 秉承着不懂就要问, ...