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#-直接创建多个类和使用反射创建类的性能的更多相关文章

  1. C# 直接创建多个类和使用反射创建类的性能

    原文:C# 直接创建多个类和使用反射创建类的性能 本文告诉大家我对比的使用直接创建多个类和使用反射创建多个类的性能 在上一篇 C# 程序内的类数量对程序启动的影响 的基础上,继续做实验 现在创建 10 ...

  2. 2019-11-29-C#-直接创建多个类和使用反射创建类的性能

    原文:2019-11-29-C#-直接创建多个类和使用反射创建类的性能 title author date CreateTime categories C# 直接创建多个类和使用反射创建类的性能 li ...

  3. agentzh 的 Nginx 教程(版本 2019.07.31)

    agentzh 的 Nginx 教程(版本 2019.07.31) agentzh 的 Nginx 教程(版本 2019.07.31) https://openresty.org/download/a ...

  4. 22.编写一个类A,该类创建的对象可以调用方法showA输出小写的英文字母表。然后再编写一个A类的子类B,子类B创建的对象不仅可以调用方法showA输出小写的英文字母表,而且可以调用子类新增的方法showB输出大写的英文字母表。最后编写主类C,在主类的main方法 中测试类A与类B。

    22.编写一个类A,该类创建的对象可以调用方法showA输出小写的英文字母表.然后再编写一个A类的子类B,子类B创建的对象不仅可以调用方法showA输出小写的英文字母表,而且可以调用子类新增的方法sh ...

  5. UE4编程之C++创建一个FPS工程(一)创建模式&角色&处理输入

    转自:http://blog.csdn.net/u011707076/article/details/44180951 从今天开始,我们一起来学习一下,如何使用C++将一个不带有任何初学者内容的空模板 ...

  6. Android(java)学习笔记66:实现Runnable接口创建线程 和 使用Callable和Future创建线程

    1. 前面说的线程的实现是新写一个子类继承Thread: 是将类声明为 Thread 的子类.该子类应重写 Thread 类的 run 方法.接下来可以分配并启动该子类的实例 2. 这里说的方案2是指 ...

  7. Java中创建操作文件和文件夹的工具类

    Java中创建操作文件和文件夹的工具类 FileUtils.java import java.io.BufferedInputStream; import java.io.BufferedOutput ...

  8. shell脚本操作mysql数据库—创建数据库,在该数据库中创建表(插入,查询,更新,删除操作也可以做)

    #!/bin/bash HOSTNAME="192.168.1.224"                                           #数据库Server信 ...

  9. 【百度地图API】如何快速创建带有标注的地图?——快速创建地图工具+如何标注商家

    原文:[百度地图API]如何快速创建带有标注的地图?--快速创建地图工具+如何标注商家 摘要: 如果你不会程序,如果你不想写代码. 如果你想拥有一张自己的地图,如果你想在该地图上标注出你商店的位置. ...

随机推荐

  1. VirtualBox的源码学习

    VMM重要的组件 TRPM (Trap Manager) PGM (Page Manager) REM (Recompiled Execution Manager) EM (Execution Man ...

  2. mkdir无法创建目录权限不够

    https://idc.wanyunshuju.com/cym/40.html 由于在公司服务器上权限问题比较复杂,我们解决这个问题是寻求服务器端人员的意见.让他们授予权限/.

  3. 用mybatis进行模糊查询总是查不到结果!

    //IStudentDao.xml @Override public List<Student> selectStudentByName(String name) { SqlSession ...

  4. PyUnit (unittest) 的用法

    PyUnit(unittest) 是 Python 自带的单元测试框架,用于编写和运行可重复的测试.PyUnit 是 xUnit 体系的一个成员,xUnit 是众多测试框架的总称,PyUnit 主要用 ...

  5. vue中wath的源码实现

    前言 阅读本节,需要理解vue的数据驱动原理. 看这样一段代码 new Vue({ data: { msg: 'hello', say: 'hello world', }, watch: { msg( ...

  6. 面向连接的echo服务编程实例

    以下是echo_serv.c的源码,提供创建服务端,绑定套接字到本机IP的8080端口,当收到客户端发送的字符串就在屏幕上打印出来,并且把字符串发送给客户端 // echo_serv.c – gcc ...

  7. 将时间 '2018-08-06T10:00:00.000Z' 格式转化为本地时间

    参考:https://blog.csdn.net/sxf_123456/article/details/81582964 参考模板: from datetime import datetime, ti ...

  8. axios的介绍及使用

    特点:支持promise API . 拦截请求和响应.转换请求数据和响应数据.取消请求.自动转换JSON数据.客户端支持防御XSRF等: axios请求方法(需后端定义):get获取数据. post提 ...

  9. position:relative/static/fixed/absolute定位的区别以及使用场景

    absolute是相对于自己最近的父元素来定位的,relative是相对于自己来定位的 relative 不脱离文档流,absolute 脱离文档流.也就是说:relative 的元素尽管表面上看到它 ...

  10. 文件上传到ftp服务工具类

    直接引用此java工具类就好 import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundExcep ...