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 代码性能分析工具
原文地址 软件开发中的性能优化对程序员来说是一个非常重要的问题.一个小问题可能成为一个大的系统的瓶颈.但是对于程序员来说,通过自身去优化代码是十分困难的.幸运的是,有一些非常棒的工具可以帮助程序员进行 ...
随机推荐
- maven 学习---Maven依赖机制
在 Maven 依赖机制的帮助下自动下载所有必需的依赖库,并保持版本升级. 案例分析 让我们看一个案例研究,以了解它是如何工作的.假设你想使用 Log4j 作为项目的日志.这里你要做什么? 1.在传统 ...
- Linux命令: ps
STAT 进程状态 S-睡眠 s-进程是会话向导进程 N拥有比普通优先级更低的 R-正在运行 D-短期等待 Z-僵尸进程 T被跟踪或者被停止 STATED 进程启动时间 TIME 进程使用CPU时间 ...
- Window平台下的静默下载并安装软件脚本bat
一,隐藏命令窗口 当我们运行bat脚本的时候,弹出CMD窗口.如果要隐藏窗口可以在bat脚本开头处写一下代码: @echo off if "%1" == "h" ...
- Linux下用火焰图进行性能分析【转】
转自:https://blog.csdn.net/gatieme/article/details/78885908 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原 ...
- time,datetime,random,os,sys,hashlib,logging,configparser,re模块
#-----time模块----- print(help(time)) #打印time帮助文档 print(time.time()) #打印时间戳 1569824501.6265268 time.sl ...
- windows删除桌面右键“英特尔@显卡设置”
运行中输入:regedit 确认运行注册表编辑器,依次单击展开 HKEY_CLASSES_ROOT\Directory\Background\shellex\ContextMenuHandlers键 ...
- 初识V4L2(一)
V4L2驱动框架概述 V4L2(video for linux two)是linux为视频设备提供的一套标准接口.它也属于字符设备驱动程序. 首先回顾普通字符设备驱动程序的写法: app : ...
- flask如何返回真正意义上的json字符串?以及中文如何正常显示?
flask中,不能直接return字典,需要把字典转换为json字符串方式有三种:1. return str(字典)2.return json.dumps(字典)3.return jsonify(字典 ...
- OpenStack Nova
OpenStack Nova 简介 OpenStack 中的 Nova 负责维护和管理云环境的计算资源 Nova 在现有 Linux 服务器上作为一组守护线程来提供服务 Nova 由多个服务器进程组成 ...
- 【oracle】 months_between(date1,date2)
(20090228,20080228)====12 (20090228,20080229)====12 (20080229,20070228)====12 (20100331,20100228)=== ...