局部变量vs静态变量内存和性能

use*_*088 1 c# performance static-members

静态变量存储在非静态方法调用中的哪里?即内部CalculateTotalStatic(),我们正在递增静态成员MyStaticVariableHolder.Total,并且也比较变量iMyStaticVariableHolder.TotalArray.Length内部的for循环.

另一方面,在此方法的另一个版本中CalculateTotalLocal(),我们使用在方法中声明的局部变量来执行上述操作.

在此期间CalculateTotalLocal,堆栈上将放置两个附加变量,这些变量将在堆栈本身(localTotallocalLength)上保存它们的值.在这种情况下会发生什么CalculateTotalStatic?它每次都从堆中访问静态变量吗?而且,CalculateTotalLocal比10%快CalculateTotalStatic.这种性能提升的正确原因是什么?

编辑 - 我想我不是很清楚 - 为此道歉.

我想说的是:

可以(根据C#规范)通过兼容的C#编译器/ JIT以与局部变量相同的方式优化静态变量访问?

 class MyStaticVariableHolder
{
    public static int[] TotalArray = new int[100];
    public static int Total = 1;
}
class Trial
{
    public void CalculateTotalStatic()
    {
        for (int i = 0; i < MyStaticVariableHolder.TotalArray.Length; i++)
        {
            MyStaticVariableHolder.Total += i;
        }

    }

    public void CalculateTotalLocal()
    {
        int localTotal = MyStaticVariableHolder.Total;
        int[] localTotalArray = MyStaticVariableHolder.TotalArray;
        int localLength = MyStaticVariableHolder.TotalArray.Length;
        for (int i = 0; i < localLength; i++)
        {
            localTotal += i;
        }
        MyStaticVariableHolder.Total = localTotal;

    }

}
Run Code Online (Sandbox Code Playgroud)

我也在看这个链接 - http://www.dotnetperls.com/local-variable-field-optimization以供参考,但我没有达到他们所获得的性能改进.

Eri*_*ert 5

静态变量存储在非静态方法调用中的哪里?

我认为你的意思是:从静态变量中取一个值,以便对它进行一些计算.因此,复制是由值.复制到什么存储?

在IL的级别,它是对评估堆栈的.运行时具有广泛的自由度,可以根据需要重新评估评估堆栈.当前线程或寄存器的堆栈都是可能的.

我注意到在某些情况下可以将副本放到堆位置.

在CalculateTotalStatic的情况下会发生什么?它每次都从堆中访问静态变量吗?

等等,谁说他们一开始就在堆里?不要求将静态变量存储在垃圾收集堆上.他们的记忆力不会被收集,为什么他们应该在堆上?(变量引用的数组当然在堆上.)

让我们改写一下.

在CalculateTotalStatic的情况下会发生什么?它是否每次都对静态变量进行全新访问?

这个问题仍然无法回答.再说一遍.

是否需要每次都从变量中执行新的提取运行时?

不允许运行时允许进行任何在单线程程序中不可见的优化.(这是一个轻微的过度陈述;有一些优化它不会执行.我不会列出它们是什么.)内化这个事实.在单线程程序中,除非移动,否则一切都是稳定的.在多线程程序中,除非保持静止,否则一切都在移动.即使在后者为真的世界中,也允许运行时假设前者.

此外,CalculateTotalLocal比CalculateTotalStatic快10%.这种性能提升的正确原因是什么?

我不知道.检查生成的代码,看看有什么区别.

可以(根据C#规范)通过兼容的C#编译器/ JIT以与局部变量相同的方式优化静态变量访问?

绝对没错.这完全属于"在单线程程序中不可见的任何优化".

此外:运行时不仅允许在其认为合适时重新排序读取和写入.它还允许允许不同的线程观察不一致的世界.如果一个线程观察到正在读取和写入的特定时间序列的变量,则允许另一个线程观察到完全不同的读取和写入交错.

此外:永远不要忘记,运行时我的意思是运行时所依赖的任何东西,比如CPU.请记住,CPU允许广泛的自由度,以便在他们认为合适的情况下重新排序读取和写入.只是因为你正在查看一些明确地将内存中的位置读入寄存器的x86代码,这与读取实际进入内存的时间完全没有任何关系.该内存位置可能已经在缓存中,主内存可能已经写在另一个线程上,有效地向后移动读取.

而且:挥发性并不一定有帮助.对于那些认为可以正确预测一个程序行为的人来说,这个程序只能在强大的内存模型上对静态变量进行易失性访问,我建议你阅读http://blog.coverity.com/2014/03/26/reordering-优化/并查看是否可以正确推断允许的读写序列.请记住,这是一个强大的记忆模型; 现在想想弱内存模型可能会有多难!

当您放弃跨线程共享内存的标准模式和实践时,您处于深水中.不要去那里.