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

title author date CreateTime categories
C# 直接建立多个类和使用反射建立类的性能
lindexi
2019-08-31 16:55:58 +0800
2018-10-12 11:24:21 +0800
C# 性能测试

本文告诉你们我对比的使用直接建立多个类和使用反射建立多个类的性能html

在上一篇 C# 程序内的类数量对程序启动的影响 的基础上,继续作实验git

如今建立 1000 个类和一个测试使用的类,测试方法请看 C# 标准性能测试github

虽然一开始就知道了反射的性能比较差,可是究竟有多差,在建立对象的时候的差别有多少?dom

反射建立对象的方法有不少个,本文就只测试其中的两个,一个是经过 Activator 的方式建立,另外一个是经过 ConstructorInfo 的方式建立ide

本文经过实际测试发现了使用 Activator 建立比直接建立慢 30 倍,经过 ConstructorInfo 建立比直接建立慢 137 倍oop

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 建立委托以大幅度提升反射调用的性能 - walterlvpost

若是关心这个结论是如何计算出来的,或者你也想使用 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 禁止优化

运行的能够看到几乎没有影响

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 %}

相关文章
相关标签/搜索