用BenchmarkDotNet看Property

  属性——Property,由get,set访问器组成,这是C#使用度比较高的类成员。今天分几组对比测试,来看一下使用Property的性能。

被测试对象:

public class MyClass
{
    private string _myProperty1 = DateTime.Now.ToString();
    public string MyProperty1 { get { return _myProperty1; } }

    public string MyProperty2 { get { return DateTime.Now.ToString(); } }

    public string MyMethod()
    {
        return DateTime.Now.ToString();
    }
}

调用测试方法统一如下:

BenchmarkRunner.Run<TestProperty>();

第一组:构造实例化对象和方法内实例化对象,调用属性差多少

[MemoryDiagnoser]
public class TestProperty
{
    private readonly MyClass _myClass;
    public TestProperty()
    {
        _myClass = new MyClass();
    }
    [Benchmark]
    public string PropertyA()
    {
        return _myClass.MyProperty1;
    }
    [Benchmark]
    public string PropertyAExt()
    {
        var myClass = new MyClass();
        return myClass.MyProperty1;
    }
}

  结果:差别很大,因为毕竟有一个new的过程,需要开销,同时也能理解,提交初始尽量初始化,多次调用时就开销变少了。

 

 

 第二组:比较用字段属性和无字段属性的差别

[MemoryDiagnoser]
public class TestProperty
{
    private readonly MyClass _myClass;
    public TestProperty()
    {
        _myClass = new MyClass();
    }
    [Benchmark]
    public string PropertyA()
    {
        return _myClass.MyProperty1;
    }
    [Benchmark]
    public string PropertyAExt()
    {
        var myClass = new MyClass();
        return myClass.MyProperty1;
    }
    [Benchmark]
    public string PropertyB()
    {
        return _myClass.MyProperty2;
    }    
    [Benchmark]
    public string PropertyBExt()
    {
        var myClass = new MyClass();
        return myClass.MyProperty2;
    }
}

结果:这组结果显示,有字段的属性更快,因为当类实体化时,字段的值已经初始化完成,所以PropertyA要好于PropertyB,关于PropertyBExt,初始化字段+实例化对象,都占了300ns。

 

 

 第三组:用反射访问属性与正常访问属性对比

[MemoryDiagnoser]
public class TestProperty
{
    private readonly MyClass _myClass;
    private readonly PropertyInfo _proinfo;
    public TestProperty()
    {
        _myClass = new MyClass();
        _proinfo = _myClass.GetType().GetProperty("MyProperty");
   }

    [Benchmark]
    public string PropertyA()
    {
        return _myClass.MyProperty1;
    }
    [Benchmark]
    public string PropertyAExt()
    {
        var myClass = new MyClass();
        return myClass.MyProperty1;
    }
    [Benchmark]
    public string PropertyB()
    {
        return _proinfo.GetValue(_myClass).ToString();

    }
    [Benchmark]
    public string PropertyBExt()
    {
        var myClass = new MyClass();
        var proinfo = myClass.GetType().GetProperty("MyProperty");
        return proinfo.GetValue(myClass).ToString();
    }
}

结果:反射调用肯定要比正常调用差一些,无可厚非,仅供参考

 

 

 第四组:重点看一下代理的性能比较

[MemoryDiagnoser]
public class TestProperty
{
    private readonly MyClass _myClass;
    private readonly PropertyInfo _proinfo;
    private readonly Func<MyClass, string> _delegate;

    public TestProperty()
    {
        _myClass = new MyClass();
        _proinfo = _myClass.GetType().GetProperty("MyProperty1");
        _delegate = (Func<MyClass, string>)Delegate.CreateDelegate(typeof(Func<MyClass, string>), _proinfo.GetGetMethod(true)!);
    }

    [Benchmark]
    public string PropertyA()
    {
        return _myClass.MyProperty1;
    }
    [Benchmark]
    public string PropertyAExt()
    {
        var myClass = new MyClass();
        return myClass.MyProperty1;
    }
    [Benchmark]
    public string PropertyB()
    {
        return _proinfo.GetValue(_myClass).ToString();
    }
    [Benchmark]
    public string PropertyBExt()
    {
        var myClass = new MyClass();
        var proinfo = myClass.GetType().GetProperty("MyProperty1");
        return proinfo.GetValue(myClass).ToString();
    }
    [Benchmark]
    public string PropertyC()
    {
        var value = _delegate(_myClass);
        return value;
    }
    [Benchmark]
    public string PropertyCExt()
    {
        var myClass = new MyClass();
        var proinfo = myClass.GetType().GetProperty("MyProperty1");
        var dele = (Func<MyClass, string>)Delegate.CreateDelegate(typeof(Func<MyClass, string>), proinfo.GetGetMethod(true)!);
        return dele(_myClass);
    }
}

结果:PropertyC代理方式与PropertyA接近,看来在其他场景中可以参考使用。但PropertyCExt要开销的多的多,看来这是提前在实例化时做了工作,所以在代理调用时才开销变少。

 

  想要更快更方便的了解相关知识,可以关注微信公众号 
 

 

 

posted @ 2022-02-07 20:37  刘靖凯  阅读(43)  评论(0编辑  收藏  举报