2019-8-31-C#-直接创建多个类和使用反射创建类的性能
| title | author | date | CreateTime | categories |
|---|---|---|---|---|
|
C# 直接创建多个类和使用反射创建类的性能
|
lindexi
|
2019-08-31 16:55:58 +0800
|
2018-10-12 11:24:21 +0800
|
C# 性能测试
|
本文告诉大家我对比的使用直接创建多个类和使用反射创建多个类的性能
在上一篇 C# 程序内的类数量对程序启动的影响 的基础上,继续做实验
现在创建 1000 个类和一个测试使用的类,测试方法请看 C# 标准性能测试
虽然一开始就知道了反射的性能比较差,但是究竟有多差,在创建对象的时候的差异有多少?
反射创建对象的方法有很多个,本文就只测试其中的两个,一个是通过 Activator 的方式创建,另一个是通过 ConstructorInfo 的方式创建
本文通过实际测试发现了使用 Activator 创建比直接创建慢 30 倍,通过 ConstructorInfo 创建比直接创建慢 137 倍
| Method | Mean | Error | StdDev | Median |
|---|---|---|---|---|
| 直接创建 | 15.90 us | 0.3173 us | 0.3116 us | 15.81 us |
| Activator 创建 | 481.28 us | 9.3487 us | 9.6004 us | 477.99 us |
| ConstructorInfo 创建 | 2,179.59 us | 84.8502 us | 242.0823 us | 2,084.09 us |
而在调用方法的速度请看图片,详细请看.NET Core/Framework 创建委托以大幅度提高反射调用的性能 - walterlv
如果关心这个结论是如何计算出来的,或者你也想使用 1000 个类,那么请继续翻到下一页
创建垃圾代码的方法
{% raw %}
private static void KicuJoosayjersere()
{
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
{{
class {pereviCirsir}
{{
public string Foo {{ get; set; }}
}}
}}"; File.WriteAllText(Path.Combine(jisqeCorenerairTurpalhee.FullName, pereviCirsir + ".cs"), nemhaSibemnoosa);
} var memtichooBowbosir=new StringBuilder();
foreach (var temp in direhelXideNa)
{
memtichooBowbosir.Append($" new {temp}();\r\n");
} var whelvejawTinaw = $@"using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes; namespace LecuryouWuruhempa
{{
public class SawstoJouweaxo
{{
[Benchmark]
public void WeejujeGaljouPemhu()
{{
{memtichooBowbosir.ToString()}
}}
}}
}}"; File.WriteAllText(Path.Combine(jisqeCorenerairTurpalhee.FullName, "SawstoJouweaxo.cs"), whelvejawTinaw);
}
{% endraw %}
这里的 WhairchooHerdo 类就是用来创建类的名
class WhairchooHerdo
{
public string LemgeDowbovou()
{
var zarwallsayKeesar = (char) _ran.Next('A', 'Z' + 1);
var lardurDairlel = new StringBuilder();
lardurDairlel.Append(zarwallsayKeesar);
for (int i = 0; i < 5; i++)
{
lardurDairlel.Append((char)_ran.Next('a', 'z'));
} return lardurDairlel.ToString();
} private Random _ran = new Random();
}
创建之后可以看到
然后将这个文件夹导入到一个新创建的项目,要求这个项目是 dotnet Framework 4.6 以上,使用下面代码做测试
using System;
using System.Diagnostics;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Toolchains.InProcess; namespace LecuryouWuruhempa
{
public class Program
{
static void Main(string[] args)
{
BenchmarkRunner.Run<SawstoJouweaxo>();
}
}
}
这时运行一下,可以看到一次运行只需要 16us 十分快
| Method | Mean | Error | StdDev |
|---|---|---|---|
| WeejujeGaljouPemhu | 16.11 us | 0.3217 us | 0.3160 us |
也许大家会说,这个方法是因为被优化了,现在添加 MethodImpl 禁止优化,请看win10 uwp 禁止编译器优化代码
运行的可以看到几乎没有影响
| Method | Mean | Error | StdDev |
|---|---|---|---|
| WeejujeGaljouPemhu | 15.68 us | 0.2810 us | 0.2628 us |
下面来对比两个不同的反射的创建方式和直接创建的速度
代码创建的方式请看文章最后
两个不同的创建方法是
Activator.CreateInstance<类型>();
和
Type cajeceKisorkeBairdi;
ConstructorInfo wimoDasrugowfo;
object relrorlelJosurpo;
cajeceKisorkeBairdi = Type.GetType("命名空间." + nameof(类型));
wimoDasrugowfo = cajeceKisorkeBairdi.GetConstructor(Type.EmptyTypes);
relrorlelJosurpo = wimoDasrugowfo.Invoke(null);
只是创建的对象有 1000 个,运行一下就可以看到文章最上面的数据
| Method | Mean | Error | StdDev | Median |
|---|---|---|---|---|
| 直接创建 | 15.90 us | 0.3173 us | 0.3116 us | 15.81 us |
| Activator 创建 | 481.28 us | 9.3487 us | 9.6004 us | 477.99 us |
| ConstructorInfo 创建 | 2,179.59 us | 84.8502 us | 242.0823 us | 2,084.09 us |
从上面的代码可以看到,反射还是很伤性能,因为这个数值在不同的设备有不同的大小,但是数值之间的比例都是差不多
可以计算出 Activator 创建比直接创建慢 30 倍,通过 ConstructorInfo 创建比直接创建慢 137 倍
创建对比直接创建和两个不同的反射方法的代码
{% raw %}
private static void BenediZayle()
{
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
{{
class {pereviCirsir}
{{
public string Foo {{ get; set; }}
}}
}}"; File.WriteAllText(Path.Combine(jisqeCorenerairTurpalhee.FullName, pereviCirsir + ".cs"), nemhaSibemnoosa);
} var memtichooBowbosir = new StringBuilder();
foreach (var temp in direhelXideNa)
{
memtichooBowbosir.Append($" new {temp}();\r\n");
} var sowastowVaiyoujall = $@"
[Benchmark]
public void WeejujeGaljouPemhu()
{{
{memtichooBowbosir.ToString()}
}}
"; memtichooBowbosir.Clear(); foreach (var temp in direhelXideNa)
{
memtichooBowbosir.Append($" Activator.CreateInstance<{temp}>();\r\n");
} var learhuseRasel = $@"
[Benchmark]
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
public void BowhempuWurrofe()
{{
{memtichooBowbosir.ToString()}
}}
"; memtichooBowbosir.Clear(); foreach (var temp in direhelXideNa)
{
memtichooBowbosir.Append(
$" cajeceKisorkeBairdi = Type.GetType(\"LecuryouWuruhempa.\" + nameof({temp}));\r\n");
memtichooBowbosir.Append(@"
wimoDasrugowfo = cajeceKisorkeBairdi.GetConstructor(Type.EmptyTypes);
relrorlelJosurpo = wimoDasrugowfo.Invoke(null);
"); } var sifurDassalcha = $@"
[Benchmark]
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
public void KonejoDewee()
{{
Type cajeceKisorkeBairdi; ConstructorInfo wimoDasrugowfo;
object relrorlelJosurpo; {memtichooBowbosir.ToString()} }}"; var whelvejawTinaw = $@"using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes; namespace LecuryouWuruhempa
{{
public class SawstoJouweaxo
{{
{sowastowVaiyoujall} {learhuseRasel} {sifurDassalcha} }}
}}"; File.WriteAllText(Path.Combine(jisqeCorenerairTurpalhee.FullName, "SawstoJouweaxo.cs"), whelvejawTinaw);
}
{% endraw %}
2019-8-31-C#-直接创建多个类和使用反射创建类的性能的更多相关文章
- C# 直接创建多个类和使用反射创建类的性能
原文:C# 直接创建多个类和使用反射创建类的性能 本文告诉大家我对比的使用直接创建多个类和使用反射创建多个类的性能 在上一篇 C# 程序内的类数量对程序启动的影响 的基础上,继续做实验 现在创建 10 ...
- 2019-11-29-C#-直接创建多个类和使用反射创建类的性能
原文:2019-11-29-C#-直接创建多个类和使用反射创建类的性能 title author date CreateTime categories C# 直接创建多个类和使用反射创建类的性能 li ...
- agentzh 的 Nginx 教程(版本 2019.07.31)
agentzh 的 Nginx 教程(版本 2019.07.31) agentzh 的 Nginx 教程(版本 2019.07.31) https://openresty.org/download/a ...
- 22.编写一个类A,该类创建的对象可以调用方法showA输出小写的英文字母表。然后再编写一个A类的子类B,子类B创建的对象不仅可以调用方法showA输出小写的英文字母表,而且可以调用子类新增的方法showB输出大写的英文字母表。最后编写主类C,在主类的main方法 中测试类A与类B。
22.编写一个类A,该类创建的对象可以调用方法showA输出小写的英文字母表.然后再编写一个A类的子类B,子类B创建的对象不仅可以调用方法showA输出小写的英文字母表,而且可以调用子类新增的方法sh ...
- UE4编程之C++创建一个FPS工程(一)创建模式&角色&处理输入
转自:http://blog.csdn.net/u011707076/article/details/44180951 从今天开始,我们一起来学习一下,如何使用C++将一个不带有任何初学者内容的空模板 ...
- Android(java)学习笔记66:实现Runnable接口创建线程 和 使用Callable和Future创建线程
1. 前面说的线程的实现是新写一个子类继承Thread: 是将类声明为 Thread 的子类.该子类应重写 Thread 类的 run 方法.接下来可以分配并启动该子类的实例 2. 这里说的方案2是指 ...
- Java中创建操作文件和文件夹的工具类
Java中创建操作文件和文件夹的工具类 FileUtils.java import java.io.BufferedInputStream; import java.io.BufferedOutput ...
- shell脚本操作mysql数据库—创建数据库,在该数据库中创建表(插入,查询,更新,删除操作也可以做)
#!/bin/bash HOSTNAME="192.168.1.224" #数据库Server信 ...
- 【百度地图API】如何快速创建带有标注的地图?——快速创建地图工具+如何标注商家
原文:[百度地图API]如何快速创建带有标注的地图?--快速创建地图工具+如何标注商家 摘要: 如果你不会程序,如果你不想写代码. 如果你想拥有一张自己的地图,如果你想在该地图上标注出你商店的位置. ...
随机推荐
- 11、testng.xml文件解析
我们可以从以下几种方式调用testng 用testng.xml ant 命令行 我们本次重点介绍testng.xml,testng.xml 文件来配置测试用例的执行 ,testng.xml 文件可以很 ...
- java-day19
获取Stream流方法 根据Collection获取流 根据Map获取流 根据数组获取流 常用方法分为两种:延迟方法和终结方法 逐一处理:forEach 过滤:filter 映射:map 统计个数:c ...
- java-day18
函数式接口在java中指:有且仅有一个抽象方法的接口 @FunctionalInterface注解:可以检测接口是否是一个函数式接口 函数式接口的使用:一般可以作为方法的参数和返回值类型 自定义函数式 ...
- 大型站点图片server架构的演进
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/dinglang_2009/article/details/31450731 在主流的Web站点中,图 ...
- [转] js对键盘输入事件绑定到特定按钮。
<script type="text/javascript" language="javascript"> document.onkeyup = f ...
- PHP之区域块链
搭建一个最简单的区块链吧.代码简单易懂. <?php //区域块链 //block 区块 // chain 链 //data //之前区块的has值 //自己的has值 : 他是由存储在区块链 ...
- Echart中X轴为时间坐标刻度时,后台返回时间List被强制转化为时间戳问题
if(recordlist!=null&&recordlist.size()>0) { for (Record record : recordlist) { //根据频次决定使用 ...
- nodejs MYSQL数据库执行多表查询
1.设计数据库 2.设计数据库表 genres表: books表: 3.安装MySQL模块 4. 代码编写 (1) 第一种方法: 在query中使用nextTables属性,将属性值设置为ture d ...
- Go 位运算符
Go 位运算符 package main import "fmt" func main() { var a uint = 60 /* 60 = 0011 1100 */ var b ...
- 后缀自动机模板——不同子串个数p2408
后缀自动机的入门博客 https://www.luogu.org/blog/Kesdiael3/hou-zhui-zi-dong-ji-yang-xie 有两种求法,分别对应了两种性质 #includ ...