2019-11-29-C#-性能分析-反射-VS-配置文件-VS-预编译
原文:2019-11-29-C#-性能分析-反射-VS-配置文件-VS-预编译
title | author | date | CreateTime | categories |
---|---|---|---|---|
C# 性能分析 反射 VS 配置文件 VS 预编译
|
lindexi
|
2019-11-29 10:13:17 +0800
|
2018-10-15 20:48:40 +0800
|
C# 性能测试
|
本文分析在 C# 中使用反射和配置文件和预编译做注入的性能,本文的数据是为预编译框架,开发高性能应用 - 课程 - 微软技术暨生态大会 2018 - walterlv提供
本文通过代码生成工具,使用C# 标准性能测试拿到三个不同的方法的性能
先来介绍一个程序的构成,这个程序里面有 1000 个类,这些类表示需要注入的类,每个类的代码大概都是这样
namespace LecuryouWuruhempa
{
[CelkaturjairQelofe]
class 类名
{
public string Foo { get; set; }
}
}
所有的类只有类名不相同,注入类的方法本文使用三个不同的方法,第一个就是预编译的方法。这里的预编译的方法就是在编译的时候,通过 Roslyn 拿到程序集里的所有类,和正常写代码一样,写出所有的类的创建和注入。
测试的类里通过一个 List<object>
作为注入的输入,也就是通过任意的方式将对应的类创建出来,放进这个列表就是注入完成。
使用预编译的方法就像直接在代码里写 new Foo()
一样
而通过配置文件的方法实际也是反射的方法,只是少了反射整个程序集找到对应的类的过程
通过读取配置文件拿到了程序集需要注入的所有类的类名,然后通过反射的方法拿到对应的 Type 再通过 Type 拿到构造函数,创建对象加入列表。本文为了防止因为读取配置文件让时间都在磁盘就直接写出了程序集的所有类
而反射的方法是反射程序集,通过判断类的 Attitude 也就是上面代码的 CelkaturjairQelofe
特性,如果一个类有这个特性,那么这个类就是需要注入的类,通过反射创建加入列表。
反射的代码都很简单,先看一下测试的数据
Method | Mean | Error | StdDev | Median | Scaled | ScaledSD |
---|---|---|---|---|---|---|
预编译 | 28.20 us | 0.3970 us | 0.3713 us | 28.16 us | 1.00 | 0.00 |
配置文件 | 2,125.77 us | 44.3371 us | 121.3722 us | 2,074.70 us | 75.39 | 4.39 |
反射特定的类 | 3,141.09 us | 47.0754 us | 41.7311 us | 3,146.11 us | 111.40 | 2.01 |
预编译如果使用委托创建,测试数据会比直接 new 的慢很多
Method | Mean | Error | StdDev | Scaled | ScaledSD |
---|---|---|---|---|---|
预编译-new | 28.48 us | 0.3682 us | 0.3445 us | 1.00 | 0.00 |
预编译-委托创建 | 61.55 us | 1.1327 us | 1.0595 us | 2.16 | 0.04 |
配置文件 | 2,098.50 us | 40.6163 us | 48.3508 us | 73.70 | 1.87 |
反射特定的类 | 3,236.56 us | 63.3132 us | 126.4434 us | 113.67 | 4.59 |
我通过设置了基线是预编译,可以看到通过配置文件创建的方式比预编译慢 75 倍,而通过反射特定的类是慢 100 多倍
其他测试请看 C# 直接创建多个类和使用反射创建类的性能
整个测试的工程我打包放在下面,这个工程的创建代码很简单,我也直接放在下面
测试的工程 C# 性能分析 反射 VS 配置文件 VS 预编译-CSDN下载
如果觉得我的数据很诡异,那么请自己运行一下
创建工程的代码不包括创建测试的工程的框架,测试项目的框架很简单,只需要创建一个空白的控制台项目,在这个控制台项目安装 BenchmarkDotNet 打开 Program 添加下面代码
using BenchmarkDotNet.Running; public class Program
{
static void Main(string[] args)
{
BenchmarkRunner.Run<SawstoJouweaxo>(); }
}
通过运行 ReecelnaxeaDrasilouhalLaigeci 方法就可以在运行的文件夹找到创建的文件夹,将这个文件夹复制到测试的工程就可以
{% raw %}
private static void ReecelnaxeaDrasilouhalLaigeci()
{
var terebawbemTitirear = new WhairchooHerdo(); List<string> direhelXideNa = new List<string>(); var jisqeCorenerairTurpalhee = new DirectoryInfo("MerelihikeLouseafoopu"); jisqeCorenerairTurpalhee.Create(); for (int i = 0; i < 1000; i++)
{
var pereviCirsir = terebawbemTitirear.LemgeDowbovou(); direhelXideNa.Add(pereviCirsir); var nemhaSibemnoosa = $@"
using System;
using System.Collections.Generic;
using System.Text; namespace LecuryouWuruhempa
{{
[CelkaturjairQelofe]
class {pereviCirsir}
{{
public string Foo {{ get; set; }}
}}
}}"; File.WriteAllText(Path.Combine(jisqeCorenerairTurpalhee.FullName, pereviCirsir + ".cs"), nemhaSibemnoosa);
} var celkaturjairQelofeAttribute = @"using System; namespace LecuryouWuruhempa
{
class CelkaturjairQelofeAttribute : Attribute
{ }
}";
File.WriteAllText(Path.Combine(jisqeCorenerairTurpalhee.FullName, "CelkaturjairQelofeAttribute.cs"), celkaturjairQelofeAttribute); var memtichooBowbosir = new StringBuilder();
foreach (var temp in direhelXideNa)
{
memtichooBowbosir.Append($" _jooyiSouse.Add(new {temp}());\r\n");
} var sowastowVaiyoujall = $@"
[Benchmark(Baseline = true, Description = ""预编译"")]
public void WeejujeGaljouPemhu()
{{
_jooyiSouse.Clear(); {memtichooBowbosir.ToString()}
}}
"; memtichooBowbosir.Clear();
memtichooBowbosir.Append($@" List<string> jeesareMewheehowBistawHorbatall = new List<string>()
{{
"); foreach (var temp in direhelXideNa)
{
memtichooBowbosir.Append($"\"{temp}\", ");
memtichooBowbosir.Append("\r\n");
} memtichooBowbosir.Append(" };"); var sifurDassalcha = $@"
[Benchmark(Description = ""配置文件"")]
public void KonejoDewee()
{{
Type cajeceKisorkeBairdi; ConstructorInfo wimoDasrugowfo;
object relrorlelJosurpo;
_jooyiSouse.Clear(); {memtichooBowbosir.ToString()} foreach (var temp in jeesareMewheehowBistawHorbatall)
{{
cajeceKisorkeBairdi = Type.GetType(""LecuryouWuruhempa."" + temp);
wimoDasrugowfo = cajeceKisorkeBairdi.GetConstructor(Type.EmptyTypes);
relrorlelJosurpo = wimoDasrugowfo.Invoke(null);
_jooyiSouse.Add(relrorlelJosurpo); }} }}"; var stoomairHem = @"
[Benchmark(Description = ""反射"")]
public void TirjeTuxemsowwherLaralJunoo()
{
_jooyiSouse.Clear(); var bermartaPallnirhi = Assembly.GetExecutingAssembly(); foreach (var temp in bermartaPallnirhi.GetTypes())
{
var wimoDasrugowfo = temp.GetConstructor(Type.EmptyTypes);
var relrorlelJosurpo = wimoDasrugowfo.Invoke(null);
_jooyiSouse.Add(relrorlelJosurpo);
}
}"; stoomairHem = ""; memtichooBowbosir.Clear(); memtichooBowbosir.Append(@" List<Func<object>> lairchurBirchalrotro = new List<Func<object>>()
{
"); foreach (var temp in direhelXideNa)
{
memtichooBowbosir.Append($" () => new {temp}(),");
memtichooBowbosir.Append("\r\n");
} memtichooBowbosir.Append(" };"); stoomairHem = $@"
[Benchmark(Description = ""委托创建"")]
public void LemjobesuDijisleci()
{{ _jooyiSouse.Clear(); {memtichooBowbosir.ToString()} foreach (var temp in lairchurBirchalrotro)
{{
_jooyiSouse.Add(temp());
}}
}}"; var drairdreBibearnou = @"
[Benchmark(Description = ""反射特定的类"")]
public void SasesoJirkoukistiCowqu()
{
_jooyiSouse.Clear(); var bermartaPallnirhi = Assembly.GetExecutingAssembly(); foreach (var temp in bermartaPallnirhi.GetTypes().Where(temp=> temp.GetCustomAttribute<CelkaturjairQelofeAttribute>() != null))
{
var wimoDasrugowfo = temp.GetConstructor(Type.EmptyTypes);
var relrorlelJosurpo = wimoDasrugowfo.Invoke(null);
_jooyiSouse.Add(relrorlelJosurpo);
}
}"; var whelvejawTinaw = $@"using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
using System.Reflection;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes; namespace LecuryouWuruhempa
{{
public class SawstoJouweaxo
{{ {sowastowVaiyoujall} {sifurDassalcha} {stoomairHem} {drairdreBibearnou} private List<object> _jooyiSouse = new List<object>(); }}
}}"; File.WriteAllText(Path.Combine(jisqeCorenerairTurpalhee.FullName, "SawstoJouweaxo.cs"), whelvejawTinaw);
}
{% endraw %}
2019-11-29-C#-性能分析-反射-VS-配置文件-VS-预编译的更多相关文章
- C# 性能分析 反射 VS 配置文件 VS 预编译
本文分析在 C# 中使用反射和配置文件和预编译做注入的性能,本文的数据是为预编译框架,开发高性能应用 - 课程 - 微软技术暨生态大会 2018 - walterlv提供 本文通过代码生成工具,使用C ...
- 2019-8-31-C#-性能分析-反射-VS-配置文件-VS-预编译
title author date CreateTime categories C# 性能分析 反射 VS 配置文件 VS 预编译 lindexi 2019-08-31 16:55:58 +0800 ...
- 2019.11.29 Mysql的数据操作
为名为name的表增加数据(插入所有字段) insert into name values(1,‘张三’,‘男’,20); 为名为name的表增加数据(插入部分字段) insert into name ...
- 2019.11.29 SAP SMTP郵件服務器配置 發送端 QQ郵箱
今天群裏的小夥伴問了如何配置郵件的問題,隨自己在sap裏面配置了一個 1. RZ10配置參數 a) 参数配置前,先导入激活版本 执行完毕后返回 b) 输入参数文件DEFAU ...
- pycharm+anaconda在Mac上的配置方法 2019.11.29
内心os: 听人说,写blog是加分项,那他就不是浪费时间的事儿了呗 毕竟自己菜还是留下来东西来自己欣赏吧 Mac小电脑上进行python数据开发环境的配置 首先下载Anaconda,一个超好用的数据 ...
- Supervision meeting notes 2019/11/29
topic 分支: 1. subgraph/subsequence mining Wang Jin, routine behavior/ motif. Philippe Fournier Viger ...
- EOJ Monthly 2019.11 E. 数学题(莫比乌斯反演+杜教筛+拉格朗日插值)
传送门 题意: 统计\(k\)元组个数\((a_1,a_2,\cdots,a_n),1\leq a_i\leq n\)使得\(gcd(a_1,a_2,\cdots,a_k,n)=1\). 定义\(f( ...
- 11个Visual Studio代码性能分析工具
软件开发中的性能优化对程序员来说是一个非常重要的问题.一个小问题可能成为一个大的系统的瓶颈.但是对于程序员来说,通过自身去优化代码是十分困难的.幸运的是,有一些非常棒的工具可以帮助程序员进行代码分析和 ...
- .NET 11 个 Visual Studio 代码性能分析工具
原文地址 软件开发中的性能优化对程序员来说是一个非常重要的问题.一个小问题可能成为一个大的系统的瓶颈.但是对于程序员来说,通过自身去优化代码是十分困难的.幸运的是,有一些非常棒的工具可以帮助程序员进行 ...
随机推荐
- 对于不返回任何键列信息的 SelectCommand,不支持 DeleteCommand 的动态 SQL 生成
VS新增操作数据库出现如下报错. 原因是数据库表未添加主键 MySQL: CREATE TABLE Customer (SID integer, Last_Name ), First_Name ), ...
- 通过jQuery给<li>绑定点击事件
背景:有个需求需要js中实现li标签的事件绑定,li通过在ajax请求中动态添加,按照常理,使用jQuery,可以使用以下方法绑定点击事件: $(function(){ commonAjaxCall ...
- The listener supports no services oracle注册监听
问题登场: [oracle@my-e450 ~]$ lsnrctl status …… The listener supports no servicesThe command completed s ...
- Transformer —— attention is all you need
https://www.cnblogs.com/rucwxb/p/10277217.html Transformer -- attention is all you need Transformer模 ...
- Hebye 深度学习中Dropout原理解析
1. Dropout简介 1.1 Dropout出现的原因 在机器学习的模型中,如果模型的参数太多,而训练样本又太少,训练出来的模型很容易产生过拟合的现象. 在训练神经网络的时候经常会遇到过拟合的问题 ...
- Ubuntu下搭建Kubernetes集群(4)--部署K8S Dashboard
K8S Dashboard是官方的一个基于WEB的用户界面,专门用来管理K8S集群,并可展示集群的状态.K8S集群安装好后默认没有包含Dashboard,我们需要额外创建它. 首先我们执行命令: wg ...
- 201871010125 王玉江《面向对象程序设计(java)》第十三周学习总结
项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...
- python爬虫之获取页面script里面的内容
这是网页上的script 我要获取的是00914这个数字 直接使用正则表达式即可 运行结果: 源码: import re from bs4 import BeautifulSoup from url ...
- 01.JAVA语言基础相关解答
1.首先,第一个问题谈到一个java类文件中真的只能有一个公有类吗?并给出了以下代码.可以看出这个程序里有两个public类: 我进行了不同的调试: ...
- luoguP3704 [SDOI2017]数字表格
题意 默认\(n\leqslant m\) 所求即为:\(\prod\limits_{i=1}^n\prod\limits_{j=1}^mf[\gcd(i,j)]\) 枚举\(\gcd(i,j)\)变 ...