C#反射,性能优化,不止于优化

 架构师的价值,在于独立且理性的思考

e6ba15e9911ae79b96dc1c9d41ad0516.jpeg

想要写出灵活而且具有更好适应性的代码,反射是首选方案。

反射赋予程序在运行时动态创建实例的能力,可以在程序运行时(而非编译时)获取实例类型,获取元数据信息,动态调用实例方法及属性,实现在通常编程逻辑中无法完成的功能,是编程体系中的高阶技能。

反射的一大弊端是性能偏低,但反射性能究竟低多少,想必并非每个开发人员都了解,那么本着严谨求实的精神,我们来分析一下反射的执行效率及其优化方案。

01

优化方案

首先说一下反射的优化方案,反射性能优化有以下几种方案:

  1. 委托

  2. ILEmit(直接编写IL,复杂度较高)

  3. 表达式树(Expression,复杂度相对较高)

  4. 元数据缓存

02

性能测试

接下来,通过对一个属性的读写操作,分析这几种方案的性能。

下图是分别采用:属性、委托、ILEmit、表达式树、元数据缓存、反射,六种方案,对一个属性进行读写操作的性能测试结果。

22d36832294943f8a56bc73ab8331df6.png         

从测试结果可以看出:

通过反射读取属性值,与直接通过属性读取,耗时相差283倍

通过反射写入属性值,与直接通过属性写入,耗时相差77倍

相对来说,反射的性能,确实差了不少。

再从绝对耗时角度看,测试结果中,操作耗时的单位是ns(纳秒),纳秒和秒的换算关系如下:

1s 
= 1000 ms(毫秒)
= 1000000 us(微秒)
= 1000000000 ns(纳秒)

取耗时最长的106 ns,相当于0.000000106 s,0.000106 ms,也就是说,即使在一个业务逻辑中,调用10000次反射设置属性操作,总耗时也只有1.06 ms,通常一个逻辑操作耗时低于10 ms时,性能优化的必要性不大(一家之言,仅供参考)。

对于性能的追求,是每个技术人应当铭记于心的准则,可以根据自己的技术能力,业务场景以及任务排期,选择采用不同的优化方案。

03


方案分析

分析一下这几种方案:

  1. 委托

对比优化方案可知,委托的性能最好,读性能提高42倍,写性能提高41倍。

委托的实现难度较低,并且代码可阅读性较好,是首选优化方案。

注意:这里的委托是指delegate(包括:Action,Func),而不是Delegate,直接使用Delegate的性能比反射还要低2倍,需要将Delegate转换为特定类型的delegate才能起到性能提升的作用。由此也带来了委托的缺点,通用性不强,需要根据不同类型,创建相应的委托。

  1. ILEmit

ILEmit相当于直接通过IL编写代码,创建过程相对复杂,代码可读性低,编写难度高,有兴趣的可以研究一下这个库Sigil。

  1. 表达式树

直接编写表达式树也有一定难度,但相对于ILEmit要简单很多,可以深入了解一下。对于属性的读写操作,可以参考FastProperty。

  1. 元数据缓存

元数据缓存是最简单的方案,在没有精力采用其他方案时,是个不错的选择,能得到30%的性能提升。

重要说明:此性能测试耗时只包含了不同方案下,属性读写操作方法的耗时,而不包含生成委托、构造ILEmit、构造表达式树的时间,如果算上这部分时间,那么这几种方案比直接使用PropertyInfo还要慢一倍,这一点一定要注意。这就给我们的优化方案提出了新的挑战,需要提前构建委托、Emit或表达式树,并进行缓存,以便后续操作使用,这样才能达到性能优化的目的

04


总结

我们常说:手里拿个锤子,看什么都像钉子。

究其原因是因为我们手里只有锤子,了解更多的方案,扩大自己的知识边界,让自己的工具箱中多几件工具,那么面对不同问题场景时,便可以多几种可选的应对方案。

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

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

相关文章

设计模式C++实现--Observer模式

2019独角兽企业重金招聘Python工程师标准>>> 观察者模式 当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。…

Liunx 安装mysql 5.6.16

2019独角兽企业重金招聘Python工程师标准>>> 1.卸载原有的mysql 1)先查看原有的mysql rpm -qa|grep -i mysql 2)删除 mysql rpm -e --nodeps 包名 3)删除老版本 mysql的开发头文件和库 rm -fr /usr/lib/mysql rm -fr /usr/include/mysql 注意:卸载后/va…

数据挖掘 pandas基础入门之操作

为什么80%的码农都做不了架构师?>>> 统计 import pandas import numpy# 通过传递一个 numpyarray,时间索引以及列标签来创建一个DataFrame: dates pandas.date_range("20180509", periods6) df pandas.DataFrame(num…

C# Task.Delay()和Thread.Sleep()有什么区别?

很多时候我们需要做一段延时处理,就直接Thread.Sleep(n)处理了,但实际上延时也可以用Task.Delay(n),那二者之间有没有区别呢?我们先来看一个案例:using System; using System.Threading; using System.Threading.Tasks…

.NET MAUI实战 MessagingCenter

1.概要在.NET MAUI提供了消息机制,该机制为订阅/发布模式。发布-订阅模式是一种消息传递模式,在此模式下,发布者可在无需知道任何接收方(称为订阅方)的情况下发送消息。同样,订阅方可在不了解任何发布方的情…

洛谷——P1033 自由落体

https://www.luogu.org/problem/show?pid1033#sub 题目描述 在高为 H 的天花板上有 n 个小球,体积不计,位置分别为 0,1,2,….n-1。在地面上有一个小车(长为 L,高为 K,距…

java 接口防刷_java轻量级接口限流/防刷插件

简介call-limit提供接口限流、防刷的功能,插件基于spring开发,在应用应用的任何一个逻辑层皆可使用(web、service、dao),插件支持单机应用下的限流和分布式应用的限流(分布式应用限流需要依赖redis),在简单业务场景下插件可为大家…

【leetcode】521. Longest Uncommon Subsequence I

题目如下: 解题思路:本题有点意思。首先如果输入的两个字符串都为空,那么结果是-1;如果两个字符串长度不一样,那么结果是较长的字符串的长度,因为较长的字符串肯定是自身的子序列,但一定不是较短…

【问题】为什么 System.Timers.Timer 更改间隔时间后的第一次触发时间是设定时间的三倍?...

【问题】为什么 System.Timers.Timer 更改间隔时间后的第一次触发时间是设定时间的三倍?独立观察员 2022 年 9 月 4 日在编写 “Wifi 固定器 [1]” 程序时,按如下方式使用了定时器:// 声明; private Timer _Timer new Timer() { …

JS魔法堂:判断节点位置关系

一、前言                           在polyfill querySelectorAll 和写弹出窗时都需要判断两个节点间的位置关系,通过jQuery我们可以轻松搞定,但原生JS呢?下面我将整理各种判断方法,以供日后查阅。 二…

ChartCtrl源码剖析之——CChartAxis类

CChartAxis类用来绘制波形控件的坐标轴,这个源码相对较复杂,当初阅读的时候耗费了不少精力来理解源码中的一些实现细节。 CChartAxis类的头文件。 #if !defined(AFX_CHARTAXIS_H__063D695C_43CF_4A46_8AA0_C7E00268E0D3__INCLUDED_) #define AFX_CHARTA…

基于.net开发的自助餐饮系统

本文系 EMQ&Intel 联合举办的首届“中国物联网数据基础设施最佳案例评选大赛“个人开发者赛道一等奖作品。项目简介智能餐饮自助结算系统是一个由称重系统、显示屏、自助扫码盒和 Intel CPU 组成的智能自助结算终端,将装有菜品的托盘放到秤盘上结算,…

java打包维护_java打包详解

from yahh2008的blog: http://www.matrix.org.cn/blog/yahh2008/兄弟,对java着迷吗,或者是为了自己的生计,不论怎样都欢迎你进入精彩java世界,welcome!可能你刚刚对每个人说:Hello World!也或者…

Linux高级文本处理之sed(三)

sed高级命令sed允许将多行内容读取到模式空间,这样你就可以匹配跨越多行的内容。本篇笔记主要介绍这些命令,它们能够创建多行模式空间并且处理之。其中,N/D/P这三个多行命令分别对应于小写的n/d/p命令,后者我们在上一篇已经介绍。…

如何在 C# 程序中注入恶意 DLL ?

一:背景 前段时间在训练营上课的时候就有朋友提到一个问题,为什么 Windbg 附加到 C# 程序后,程序就处于中断状态了?它到底是如何实现的?其实简而言之就是线程的远程注入,这一篇就展开说一下。二&#xff1a…

练习题|网络编程-socket开发

原文:https://www.cnblogs.com/shengyang17/p/8822745.html 1、什么是C/S架构? C指的是client(客户端软件),S指的是Server(服务端软件),C/S架构的软件,实现服务端软件与客…

ABP vNext微服务架构详细教程(补充篇)——单层模板(上)

简介在之前的《ABP vNext微服务架构详细教程》系列中,我们已经构建了完整的微服务架构实例,但是在开发过程中,我们会发现每个基础服务都包含10个类库,这是给予DDD四层架构下ABP的实现方案,但是实际使用中我们会发现&am…

mybatis源码学习(三):MappedStatement的解析过程

我们之前介绍过MappedStatement表示的是XML中的一个SQL。类当中的很多字段都是SQL中对应的属性。我们先来了解一下这个类的属性: public final class MappedStatement {private String resource;private Configuration configuration;//sql的IDprivate String id;//…

C# 二十年语法变迁之 C# 8参考

C# 二十年语法变迁之 C# 8参考自从 C# 于 2000 年推出以来,该语言的规模已经大大增加,我不确定任何人是否有可能在任何时候都对每一种语言特性都有深入的了解。因此,我想写一系列快速参考文章,总结自 C# 2.0 以来所有主要的新语言…

windows 提权 cve-2018-8897

windows 提权 cve-2018-8897影响范围:基本上是全版本具体影响范围看详情:https://portal.msrc.microsoft.co … isory/CVE-2018-8897http://www.o2oxy.cn/wp-content/uploads/2018/06/cve-2018-8897.rar转载于:https://blog.51cto.com/9861015/2126608