属于公共领域的不断OK? [英] Are public fields ever OK?

查看:298
本文介绍了属于公共领域的不断OK?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在你的肠道反应,像我一样一开始,读取整个的问题,请。我知道,他们让你觉得脏,我知道我们都被烧毁之前,我知道这不是好作风,但是,在公共领域不断好吗?

Before you react from the gut, as I did initially, read the whole question please. I know they make you feel dirty, I know we've all been burned before and I know it's not "good style" but, are public fields ever ok?

我的工作,创建并与工作在一个结构的内存模型形成相当规模的工程应用程序(任何来自高层建筑的桥梁脱落,没关系)。有参与这个项目几何分析和计算的吨。为了支持这一点,模型是由许多微小的不可改变的只读结构以重新present像点,线段,等。这些结构(像点的坐标)的值的被访问几十或一个典型的程序执行期间几亿次。因为模型的复杂性和计算的体积的,性能是绝对关键的。

I'm working on a fairly large scale engineering application that creates and works with an in memory model of a structure (anything from high rise building to bridge to shed, doesn't matter). There is a TON of geometric analysis and calculation involved in this project. To support this, the model is composed of many tiny immutable read-only structs to represent things like points, line segments, etc. Some of the values of these structs (like the coordinates of the points) are accessed tens or hundreds of millions of times during a typical program execution. Because of the complexity of the models and the volume of calculation, performance is absolutely critical.

我觉得我们正在尽一切努力来优化我们的算法,性能测试,以确定瓶颈,使用正确的数据结构,等等,等等,我不认为这是premature优化的情况下。性能测试幅度显示顺序访问字段,而不是直接通过对象上的属性时,(至少)的性能提升。鉴于这一信息,而事实上,我们也可以公开的信息相同的属性支持数据绑定和其他情况...这行吗? 记住,阅读一成不变的结构仅领域。的任何人都可以想出一个理由,我会后悔吗?

I feel that we're doing everything we can to optimize our algorithms, performance test to determine bottle necks, use the right data structures, etc. etc. I don't think this is a case of premature optimization. Performance tests show order of magnitude (at least) performance boosts when accessing fields directly rather than through a property on the object. Given this information, and the fact that we can also expose the same information as properties to support data binding and other situations... is this OK? Remember, read only fields on immutable structs. Can anyone think of a reason I'm going to regret this?

下面是一个示例测试程序:

Here's a sample test app:


struct Point {
    public Point(double x, double y, double z) {
        _x = x;
        _y = y;
        _z = z;
    }

    public readonly double _x;
    public readonly double _y;
    public readonly double _z;

    public double X { get { return _x; } }
    public double Y { get { return _y; } }
    public double Z { get { return _z; } }
}

class Program {
    static void Main(string[] args) {
        const int loopCount = 10000000;

        var point = new Point(12.0, 123.5, 0.123);

        var sw = new Stopwatch();
        double x, y, z;
        double calculatedValue;
        sw.Start();
        for (int i = 0; i < loopCount; i++) {
            x = point._x;
            y = point._y;
            z = point._z;
            calculatedValue = point._x * point._y / point._z;
        }
        sw.Stop();
        double fieldTime = sw.ElapsedMilliseconds;
        Console.WriteLine("Direct field access: " + fieldTime);

        sw.Reset();
        sw.Start();
        for (int i = 0; i < loopCount; i++) {
            x = point.X;
            y = point.Y;
            z = point.Z;
            calculatedValue = point.X * point.Y / point.Z;
        }
        sw.Stop();
        double propertyTime = sw.ElapsedMilliseconds;
        Console.WriteLine("Property access: " + propertyTime);

        double totalDiff = propertyTime - fieldTime;
        Console.WriteLine("Total difference: " + totalDiff);
        double averageDiff = totalDiff / loopCount;
        Console.WriteLine("Average difference: " + averageDiff);

        Console.ReadLine();
    }
}



结果:
直接字段访问:3262
属性访问:24248
总的区别:20986
平均差异:0.00020986

result:
Direct field access: 3262
Property access: 24248
Total difference: 20986
Average difference: 0.00020986


这是的只有的21秒,但为什么不呢?

It's only 21 seconds, but why not?

推荐答案

您的测试是不是真的公平的财产为基础的版本。该JIT是足够聪明,内联简单的属性,使他们有相当于直接字段访问一个运行时的性能,但它似乎并不够聪明(今天)来检测时的属性访问常量。

Your test isn't really being fair to the property-based versions. The JIT is smart enough to inline simple properties so that they have a runtime performance equivalent to that of direct field access, but it doesn't seem smart enough (today) to detect when the properties access constant values.

在你的榜样,领域获得的版本,整个循环体被优化掉,成为刚:

In your example, the entire loop body of the field access version is optimized away, becoming just:

for (int i = 0; i < loopCount; i++)
00000025  xor         eax,eax 
00000027  inc         eax  
00000028  cmp         eax,989680h 
0000002d  jl          00000027 
}

而第二个版本,实际上是执行浮点除法对每次迭代:

whereas the second version, is actually performing the floating point division on each iteration:

for (int i = 0; i < loopCount; i++)
00000094  xor         eax,eax 
00000096  fld         dword ptr ds:[01300210h] 
0000009c  fdiv        qword ptr ds:[01300218h] 
000000a2  fstp        st(0) 
000000a4  inc         eax  
000000a5  cmp         eax,989680h 
000000aa  jl          00000096 
}

制作只是两个小的变化,以您的应用程序,使之更加切合实际,使这两个操作中的性能几乎相同。

Making just two small changes to your application to make it more realistic makes the two operations practically identical in performance.

首先,随机的输入值,使它们不是常数和JIT是不是足够聪明,完全删除该部门。

First, randomize the input values so that they aren't constants and the JIT isn't smart enough to remove the division entirely.

从变化:

Point point = new Point(12.0, 123.5, 0.123);

Random r = new Random();
Point point = new Point(r.NextDouble(), r.NextDouble(), r.NextDouble());

其次,确保每个循环迭代的结果是什么地方使用:

Secondly, ensure that the results of each loop iteration are used somewhere:

每次循环前,设置calculatedValue = 0,因此它们都开始于相同点。每个循环调用Console.WriteLine后(calculatedValue.ToString()),以确保其结果是拿来主义,因此编译器不会优化它拿走。最后,使得每次迭代使用来自calculatedValue = ...改变循环体为calculatedValue + = ...

Before each loop, set calculatedValue = 0 so they both start at the same point. After each loop call Console.WriteLine(calculatedValue.ToString()) to make sure that the result is "used" so the compiler doesn't optimize it away. Finally, change the body of the loop from "calculatedValue = ..." to "calculatedValue += ..." so that each iteration is used.

在我的机器上,这些变化(有一个发布版本)产生以下结果:

On my machine, these changes (with a release build) yield the following results:

Direct field access: 133
Property access: 133
Total difference: 0
Average difference: 0

正如我们预计,在x86每个这些改性环是相同的(除了环路地址)

Just as we expect, the x86 for each of these modified loops is identical (except for the loop address)

000000dd  xor         eax,eax 
000000df  fld         qword ptr [esp+20h] 
000000e3  fmul        qword ptr [esp+28h] 
000000e7  fdiv        qword ptr [esp+30h] 
000000eb  fstp        st(0) 
000000ed  inc         eax  
000000ee  cmp         eax,989680h 
000000f3  jl          000000DF (This loop address is the only difference)

这篇关于属于公共领域的不断OK?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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