c# - 局部变量与静态变量内存和性能

标签 c# performance static-members

静态变量存储在非静态方法调用中的什么位置? IE。在 CalculateTotalStatic() 中,我们递增静态成员 MyStaticVariableHolder.Total 并且还将变量 iMyStaticVariableHolder.TotalArray 进行比较。 for 循环内的长度

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

CalculateTotalLocal 期间,将有两个额外的变量放置在堆栈上,它们会将它们的值保存在堆栈本身(localTotallocalLength )。 CalculateTotalStatic 会发生什么?它是否每次都从堆中访问静态变量?此外,CalculateTotalLocalCalculateTotalStatic 快 10%。这种性能提升的正确原因是什么?

编辑 - 我想我不是很清楚 - 对此表示歉意。

我想说的是:

能否(根据 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;

    }

}

我也在看这个链接 - http://www.dotnetperls.com/local-variable-field-optimization供引用,但我没有达到他们所获得的性能提升。

最佳答案

Where are static variables stored inside a non static method call?

我认为你的意思是:从静态变量中获取一个值,以便对其执行一些计算。因此,复制了该值。复制到什么存储空间?

在 IL 级别,它被纳入评估堆栈。运行时具有广泛的自由度来具体化评估堆栈,但它喜欢。当前线程的栈,或者寄存器都有可能。

我注意到在某些情况下可以将副本复制到堆位置。

What happens in the case of CalculateTotalStatic? Does it access the static variables from the heap every time?

等等,谁说他们一开始就在堆上?不需要将静态变量存储在垃圾收集堆上。他们的内存不会被收集,那么他们为什么要在堆上呢? (变量引用的数组当然在堆上。)

我们换个说法。

What happens in the case of CalculateTotalStatic? Does it do a fresh access to the static variable every time?

这个问题仍然没有答案。再次改写。

Is the runtime required to do a fresh fetch from the variable every time?

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

Also, CalculateTotalLocal is 10% faster than CalculateTotalStatic. What is the correct reason for this performance improvement?

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

can (according to C# spec) static variable access be optimized the same way as local variable by compliant C# compiler/JIT?

绝对是的。这完全属于“在单线程程序中不可见的任何优化”。

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

此外:不要忘记运行时我的意思是运行时所依赖的任何东西,比如CPU。请记住,CPU 被允许在他们认为合适的时候重新排序读取和写入。仅仅因为您正在查看一些 x86 代码,该代码明确地将内存中的位置读取到寄存器中,这与读取实际进入内存的时间绝对没有任何关系。该内存位置可能已经在缓存中,并且主内存可能已经写入另一个线程,从而有效地将读取时间向后移动。

此外: volatile 不一定有帮助。对于那些相信他们可以正确预测在 strong 内存模型上只能对静态变量进行 volatile 访问的程序的行为的人,我鼓励您阅读 http://blog.coverity.com/2014/03/26/reordering-optimizations/看看你是否能正确推断出允许的读写序列。请记住,这是基于 strong 内存模型的;现在想想在弱内存模型上可能会有多困难!

当您放弃跨线程共享内存的标准模式和实践时,您就陷入了困境。不要去那里。

关于c# - 局部变量与静态变量内存和性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35705878/

相关文章:

c# - 为什么我的 WPF 应用程序不显示?

javascript - 如何在 JavaScript 中有效地使用共享缓冲区的类型化数组?

performance - ElasticSearch中_source字段对大型文档(提取的PDF书籍,文档等)有什么影响?

c++ - 静态变量和初始化

java - 通过设置静态字段禁用一个静态方法调用的 if-Condition

c# - Windows 或 ASP.NET 服务中的 System.Drawing

c# - 如何读取在 C# 中打开的文件?

sql-server - NamedParameterJdbcTemplate 导致不需要的元数据调用

c++ - 具有继承的静态变量的行为

c# - 找不到类型或命名空间名称 '...'(是否缺少 using 指令或程序集引用?)