• 用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要开销的多的多,看来这是提前在实例化时做了工作,所以在代理调用时才开销变少。

     

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

     

  • 相关阅读:
    [置顶] Docker学习总结(3)——Docker实战之入门以及Dockerfile(三)
    [置顶] Docker学习总结(2)——Docker实战之入门以及Dockerfile(二)
    Vue-Router中History模式【华为云分享】
    Linux系统通过FTP进行文档基本操作【华为云分享】
    窥探日志的秘密【华为云分享】
    弹性负载均衡:负载无限,均衡有道【华为云分享】
    不给糖果就捣乱,用Python绘制有趣的万圣节南瓜怪【华为云分享】
    机器学习笔记(八)---- 神经网络【华为云分享】
    还在为运维烦恼?体验云上运维服务,提意见赢好礼!【华为云分享】
    Vue+ElementUI项目使用webpack输出MPA【华为云分享】
  • 原文地址:https://www.cnblogs.com/axzxs2001/p/15869116.html
Copyright © 2020-2023  润新知