字段与属性.性能优化 [英] Field vs Property. Optimisation of performance

查看:13
本文介绍了字段与属性.性能优化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请注意此问题仅与性能有关.让我们跳过设计指南、哲学、兼容性、可移植性以及任何与纯性能无关的东西.谢谢.

Please note this question related to performance only. Lets skip design guidelines, philosophy, compatibility, portability and anything what is not related to pure performance. Thank you.

现在问题来了.我一直认为,因为 C# 的 getter/setter 确实是变相的方法,所以读取公共字段必须比调用 getter 更快.

Now to the question. I always assumed that because C# getters/setters are really methods in disguise then reading public field must be faster than calling a getter.

所以为了确保我做了一个测试(下面的代码).但是,此测试仅产生预期结果(即字段比 getter 快 34%)如果您从 Visual Studio 内部运行它.

So to make sure I did a test (the code below). However this test only produces expected results (ie fields are faster than getters at 34%) if you run it from inside Visual Studio.

一旦你从命令行运行它,它就会显示几乎相同的时间......

Once you run it from command line it shows pretty much the same timing...

唯一的解释可能是 CLR 做了额外的优化(如果我错了,请纠正我).

The only explanation could be is that the CLR does additional optimisation (correct me if I am wrong here).

我不相信在实际应用中,这些属性以更复杂的方式使用,它们会以相同的方式进行优化.

I do not believe that in real application where those properties being used in much more sophisticated way they will be optimised in the same way.

请帮助我证明或反驳现实生活中属性比字段慢的想法.

Please help me to prove or disprove the idea that in real life properties are slower than fields.

问题是 - 我应该如何修改测试类以使 CLR 更改行为,以便公共字段优于 getter.或者告诉我任何没有内部逻辑的属性都将执行与字段相同的操作(至少在 getter 上)

我只是在谈论发布 x64 版本.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace PropertyVsField
{
    class Program
    {
        static int LEN = 20000000;
        static void Main(string[] args)
        {
            List<A> a = new List<A>(LEN);
            List<B> b = new List<B>(LEN);

            Random r = new Random(DateTime.Now.Millisecond);

            for (int i = 0; i < LEN; i++)
            {
                double p = r.NextDouble();
                a.Add(new A() { P = p });
                b.Add(new B() { P = p });
            }

            Stopwatch sw = new Stopwatch();

            double d = 0.0;

            sw.Restart();
            for (int i = 0; i < LEN; i++)
            {
                d += a[i].P;
            }

            sw.Stop();

            Console.WriteLine("auto getter. {0}. {1}.", sw.ElapsedTicks, d);

            sw.Restart();
            for (int i = 0; i < LEN; i++)
            {
                d += b[i].P;
            }

            sw.Stop();

            Console.WriteLine("      field. {0}. {1}.", sw.ElapsedTicks, d);

            Console.ReadLine();
        }
    }

    class A
    {
        public double P { get; set; }
    }
    class B
    {
        public double P;
    }
}

推荐答案

正如其他人已经提到的,getter 是内联的.

As others have already mentioned, the getters are inlined.

如果你想避免内联,你必须

If you want to avoid inlining, you have to

  • 用手动属性替换自动属性:

  • replace the automatic properties with manual ones:

class A 
{
    private double p;
    public double P
    {
        get { return p; }
        set { p = value; }
    }
} 

  • 并告诉编译器不要内联 getter(或两者,如果您愿意):

  • and tell the compiler not to inline the getter (or both, if you feel like it):

            [MethodImpl(MethodImplOptions.NoInlining)]
            get { return p; }
    

  • 请注意,第一个更改不会对性能产生影响,而第二个更改则显示出明显的方法调用开销:

    Note that the first change does not make a difference in performance, whereas the second change shows a clear method call overhead:

    手动属性:

    auto getter. 519005. 10000971,0237547.
          field. 514235. 20001942,0475098.
    

    没有内联getter:

    No inlining of the getter:

    auto getter. 785997. 10000476,0385552.
          field. 531552. 20000952,077111.
    

    这篇关于字段与属性.性能优化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆