C# 直接建立多個類和使用反射建立類的性能

本文告訴你們我對比的使用直接建立多個類和使用反射建立多個類的性能html

在上一篇 C# 程序內的類數量對程序啓動的影響 的基礎上,繼續作實驗dom

如今建立 1000 個類和一個測試使用的類,測試方法請看 C# 標準性能測試ide

雖然一開始就知道了反射的性能比較差,可是究竟有多差,在建立對象的時候的差別有多少?oop

反射建立對象的方法有不少個,本文就只測試其中的兩個,一個是經過 Activator 的方式建立,另外一個是經過 ConstructorInfo 的方式建立post

本文經過實際測試發現了使用 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 個類,那麼請繼續翻到下一頁優化

建立垃圾代碼的方法ui

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);
        }

這裏的 WhairchooHerdo 類就是用來建立類的名spa

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 倍

建立對比直接建立和兩個不一樣的反射方法的代碼

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);
        }
相關文章
相關標籤/搜索