C# 性能分析 反射 VS 配置文件 VS 预编译
本文分析在 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 方法就可以在运行的文件夹找到创建的文件夹,将这个文件夹复制到测试的工程就可以
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);
}
我搭建了自己的博客 https://blog.lindexi.com/ 欢迎大家访问,里面有很多新的博客。只有在我看到博客写成熟之后才会放在csdn或博客园,但是一旦发布了就不再更新
如果在博客看到有任何不懂的,欢迎交流,我搭建了 dotnet 职业技术学院 欢迎大家加入
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。
C# 性能分析 反射 VS 配置文件 VS 预编译的更多相关文章
- 2019-11-29-C#-性能分析-反射-VS-配置文件-VS-预编译
原文:2019-11-29-C#-性能分析-反射-VS-配置文件-VS-预编译 title author date CreateTime categories C# 性能分析 反射 VS 配置文件 V ...
- 2019-8-31-C#-性能分析-反射-VS-配置文件-VS-预编译
title author date CreateTime categories C# 性能分析 反射 VS 配置文件 VS 预编译 lindexi 2019-08-31 16:55:58 +0800 ...
- C预编译, 预处理, C/C++头文件, 编译控制,
在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的 ...
- 【JDBC】预编译SQL与防注入式攻击
在JDBC编程中,常用Statement.PreparedStatement 和 CallableStatement三种方式来执行查询语句,其中 Statement 用于通用查询, PreparedS ...
- JDBC编程之预编译SQL与防注入式攻击以及PreparedStatement的使用教程
转载请注明原文地址: http://www.cnblogs.com/ygj0930/p/5876951.html 在JDBC编程中,常用Statement.PreparedStatement 和 ...
- JDBC编程之预编译SQL与防注入
在JDBC编程中,常用Statement.PreparedStatement 和 CallableStatement三种方式来执行查询语句,其中 Statement 用于通用查询, PreparedS ...
- mybatis深入理解之 # 与 $ 区别以及 sql 预编译
mybatis 中使用 sqlMap 进行 sql 查询时,经常需要动态传递参数,例如我们需要根据用户的姓名来筛选用户时,sql 如下: select * from user where name = ...
- mybatis之 # 与 $ 区别以及 sql 预编译
mybatis 中使用 sqlMap 进行 sql 查询时,经常需要动态传递参数,例如我们需要根据用户的姓名来筛选用户时,sql 如下: select * from user where name = ...
- mybatis深入理解(一)之 # 与 $ 区别以及 sql 预编译
mybatis 中使用 sqlMap 进行 sql 查询时,经常需要动态传递参数,例如我们需要根据用户的姓名来筛选用户时,sql 如下: select * from user where name = ...
随机推荐
- Emacs用JDEE编写Android程序
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/sheismylife/article/details/24842669 前文介绍了怎样用Maven构 ...
- Directx11教程41 纹理映射(11)
原文:Directx11教程41 纹理映射(11) 1.第一副图我们采用各性异性的滤波方式,并设置最大各性异性值为8. samplerDesc.Filter = D3D11_FILT ...
- WPF/Silverlight深度解决方案:(六)HLSL自定义渲染特效之完美攻略(上)
原文:WPF/Silverlight深度解决方案:(六)HLSL自定义渲染特效之完美攻略(上) Shader Effect种位图特效及2种渲染特效,而Silverlight中仅有这2种渲染特效: Bl ...
- python 别名
- Python学习之路3☞编程风格
语句和语法 # 表示注释掉的内容 \ 续行 print("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy\ yyyyyyyyyyyyyyyyyyyyyyy& ...
- SPA是什么?
认识SPA 最早单页面的应用无从知晓,在2004年,google的Gmail就使用了单页面.到了2010年,随着Backbone的问世之后,此概念才慢慢热了起来. 随着后来React.Angular. ...
- C++继承与构造函数、复制控制
每个派生类对象由派生类中定义的(非static)成员加上一个或多个基类子对象构成,因此,当构造.复制.赋值和撤销派生类型对象时,也会构造.复制.赋值和撤销这些基类子对象. 构造函数和复制控制成员不能继 ...
- 《C程序设计语言》笔记(三)
六:结构 1:结构体声明中,比如: struct point{ int x; int y; }; struct后面的名字是可选的,称为结构标记.结构成员.结构标记和普通变量可以采用相同的名字,它们之间 ...
- this 、静态变量
/*作者:qingfeng日期:2017/2/18功能:this,静态变量(类变量)*/class Demo3_2{ public static void main(String args[]) ...
- 12 Top Open Source Data Analytics Apps
1. Hadoop It would be impossible to talk about open source data analytics without mentioning Hadoop. ...