2019-8-31-C#-性能分析-反射-VS-配置文件-VS-预编译
| title | author | date | CreateTime | categories |
|---|---|---|---|---|
|
C# 性能分析 反射 VS 配置文件 VS 预编译
|
lindexi
|
2019-08-31 16:55:58 +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-8-31-C#-性能分析-反射-VS-配置文件-VS-预编译的更多相关文章
- C# 性能分析 反射 VS 配置文件 VS 预编译
本文分析在 C# 中使用反射和配置文件和预编译做注入的性能,本文的数据是为预编译框架,开发高性能应用 - 课程 - 微软技术暨生态大会 2018 - walterlv提供 本文通过代码生成工具,使用C ...
- 2019-11-29-C#-性能分析-反射-VS-配置文件-VS-预编译
原文:2019-11-29-C#-性能分析-反射-VS-配置文件-VS-预编译 title author date CreateTime categories C# 性能分析 反射 VS 配置文件 V ...
- CPU性能分析
CPU性能分析工具 lscpu:查看CPU硬件信息 lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Litt ...
- [Golang]字符串拼接方式的性能分析
本文100%由本人(Haoxiang Ma)原创,如需转载请注明出处. 本文写于2019/02/16,基于Go 1.11.至于其他版本的Go SDK,如有出入请自行查阅其他资料. Overview 写 ...
- Android性能分析之TraceView的使用
TraceView简介 TraceView是AndroidSDK里面自带的工具,用于对Android的应用程序以及Framework层的代码进行性能分析. TraceView是图形化的工具,最终它会产 ...
- 1.linux服务器的性能分析与优化
[教程主题]:1.linux服务器的性能分析与优化 [课程录制]: 创E [主要内容] [1]影响Linux服务器性能的因素 操作系统级 CPU 目前大部分CPU在同一时间只能运行一个线程,超线程的处 ...
- 性能分析之-- JAVA Thread Dump 分析综述
性能分析之-- JAVA Thread Dump 分析综述 一.Thread Dump介绍 1.1什么是Thread Dump? Thread Dump是非常有用的诊断Java应用问题的工 ...
- 【J2EE性能分析篇】JVM参数对J2EE性能优化的影响
一切J2EE应用都是基于JVM的,那么对于JVM的设置和监控,成为J2EE应用程序性能分析和性能优化的必然手段.今天Sincky和大家交流该话题.这里以Tomcat环境为例,其它WEB服务器如Jbos ...
- Python性能分析指南
http://www.admin10000.com/document/2861.html 尽管并非每个你写的Python程序都需要严格的性能分析,但了解一下Python的生态系统中很多优秀的在你需要做 ...
随机推荐
- dex2jar+jd-gui反编译apk的使用方法
1.将要反编译的APK后缀名改为.rar或 .zip,并解压 2.得到其中的classes.dex文件(它就是java文件编译再通过dx工具打包而成的),将获取到的classes.dex放到之前解压出 ...
- js隐式类型转换,预编译、递归、作用域,作用域链、闭包、立即执行函数、继承圣杯模式
隐式类型转换 调用Number()当有运算符(加减乘除,求余)时,会调用Number()转为数字再运算,除了 加 当 有字符串时就变身成拼接Boolean();String(); typeof()st ...
- Delphi 第一课
Delphi 是面向对象的 可视化的集成开发环境 对象包括属性 方法 事件. 用户事件 对象响应事件 不同的对象响应事件不一样
- CSIC_716_20191111【函数对象、名称空间、作用域、global 和nonlocal】
函数名是可以被引用,传递的是函数的内存地址.函数名赋值给变量后,只需要在变量后加上括号即可调用函数. 名称空间 内置名称空间:在python解释器中提前定义完的名字 全局名称空间:if.while.f ...
- css---7自定义字体
1.Adobe illustrator AI是一种应用于出版.多媒体和在线图像的工业标准矢量插画的软件,是一款非常好的矢量图形处理工具. 该软件主要应用于印刷出版.海报书籍排版.专业插画.多媒体图像处 ...
- a^a^a^a^a^a^a^a^a
a^a^a^a是从前向后算,也就是a^(a^3)
- 【转载】Abstract Factory Step by Step --- 抽象工厂
抽象工厂是创建型模式的代表,其他的还有单件(Singleton).生成器(Builder).工厂方法(Factory Method)以及原型(Prototype),模式本身没有好坏之分,只有适用不适用 ...
- iOS开发NSLayoutConstraint代码自动布局
1.NSLayoutConstraint简介 适配界面大多用Masonry工具,也是基于NSLayoutConstraint写的!通过使用两个类方法实现自动布局: + (NSArray<__ki ...
- HDU-1423-Greatest Common Increasing Subsequence-最长公共上升子序列【模版】
This is a problem from ZOJ 2432.To make it easyer,you just need output the length of the subsequence ...
- shell $* 和$@ 的区别以及运算操作
#! /bin/bash test() { echo "未加引号,二者相同" echo $* echo $@ # 脚本名 echo $ # 参数个数 echo $# # 返回值 e ...