C# 为什么访问静态数组引用比访问非静态数组引用慢

C# 为什么访问静态数组引用比访问非静态数组引用慢,c#,optimization,C#,Optimization,请看一下这个片段: public class StringToggler { static readonly bool[] ToggleableLatinChars = new[] { // 256 bools here }; readonly bool[] LocalToggleableLatinChars = ToggleableLatinChars; public string Toggle(string s) {

请看一下这个片段:

public class StringToggler
{
    static readonly bool[] ToggleableLatinChars = new[]
    {
        // 256 bools here
    };

    readonly bool[] LocalToggleableLatinChars = ToggleableLatinChars;

    public string Toggle(string s)
    {
        // blah blah

        if (LocalToggleableLatinChars[(byte) ch])
        {
            // blah blah
        }

        // blah blah
    }

    // blah blah
}
与直接使用gleablelatinchars相比,该代码的测试速度明显更快(7%ish)。 (在方法中使用ToggleableLatinChars的本地引用也会以同样的速度加快)

只有在编译.NET4时才会注意到这种效果。 在为.NET3.5编译时,我看到了相反的效果——使用静态数组明显更快。(我的机器是运行Windows 7 64位的Intel i5,正在为x86编译)

知道为什么吗

更新: 这是一个完整的代码示例,它更类似于Marc的测试示例。注意,我现在使用的是静态和局部变量版本(不再是成员变量)。虽然我看到的与原始测试代码的差异较小,但在为.NET4编译时,本地版本总是更快。你可以交换跑步顺序,但本地人总是为我赢。(为.NET 3.5编译时并没有做到这一点:它总体上比.NET 4快得多,而静态编译则更快或相同)

使用系统;
使用系统诊断;
利用制度全球化;
内部课程计划
{
const int RepeatCount=500000;
const string TestString1\u Unicode=@?=3.1415926?!a!!%ÜBERGRö223; EN!!???e=2.71828182?!!$^i^/!$;
常量字符串TestString2_Numbers=@“p=3.14159265358979323846264338327950288419716939937510…”;
const string TestString3_LowerCase=@“永远不要估计在larg grupp中的呆子piplz的数量!\*^*/”;
const string TestString4\U大写=@“伙计,你为什么在这里?你应该在会议上(废话)$\*o*/$!”;
静态void Main()
{
RunTestsStaticAccess();
RunTestsLocalAccess();
Console.ReadLine();
}
公共静态void RunTestsLocalAccess()
{
StringToggler st=新的StringToggler();
var watch=Stopwatch.StartNew();
对于(int i=0;i如果(ch简单地说:不是。我不相信你(没有提供)的测试:

我的结果:

InstanceField: 6035ms
LocalVariable: 5373ms
StaticFieldStaticInitializer: 5364ms
StaticFieldNoInitializer: 5388ms
这与我期望从额外的ldarg0和ldfld(从实例字段获取值)而不是更简单的ldsfld(从静态字段获取值)或ldloc0(从局部变量获取值)得到的结果有关

我的代码:

class Program
{
    static void Main()
    {
        new InstanceField().RunTests();
        new LocalVariable().RunTests();
        new StaticFieldStaticInitializer().RunTests();
        new StaticFieldNoInitializer().RunTests();
        Console.ReadLine();
    }
    class InstanceField
    {
        public bool[] arr= new bool[1024];
        public void RunTests()
        {
            var watch = Stopwatch.StartNew();
            int count = 0;
            for (int i = 0; i < 500000; i++)
            {
                for (int j = 0; j < arr.Length; j++)
                {
                    if (arr[j]) count++;
                }
            }
            watch.Stop();
            Console.WriteLine("{0}: {1}ms", GetType().Name, watch.ElapsedMilliseconds);
        }
    }
    class LocalVariable
    {
        public void RunTests()
        {
            bool[] arr = new bool[1024];
            var watch = Stopwatch.StartNew();
            int count = 0;
            for (int i = 0; i < 500000; i++)
            {
                for (int j = 0; j < arr.Length; j++)
                {
                    if (arr[j]) count++;
                }
            }
            watch.Stop();
            Console.WriteLine("{0}: {1}ms", GetType().Name, watch.ElapsedMilliseconds);
        }
    }
    class StaticFieldStaticInitializer
    {
        public static bool[] arr = new bool[1024];
        public void RunTests()
        {
            var watch = Stopwatch.StartNew();
            int count = 0;
            for (int i = 0; i < 500000; i++)
            {
                for (int j = 0; j < arr.Length; j++)
                {
                    if (arr[j]) count++;
                }
            }
            watch.Stop();
            Console.WriteLine("{0}: {1}ms", GetType().Name, watch.ElapsedMilliseconds);
        }
    }
    class StaticFieldNoInitializer
    {
        public static bool[] arr;
        public void RunTests()
        {                
            arr = new bool[1024];
            var watch = Stopwatch.StartNew();
            int count = 0;
            for (int i = 0; i < 500000; i++)
            {
                for (int j = 0; j < arr.Length; j++)
                {
                    if (arr[j]) count++;
                }
            }
            watch.Stop();
            Console.WriteLine("{0}: {1}ms", GetType().Name, watch.ElapsedMilliseconds);
        }
    }
}
class Program
{
    static void Main()
    {
        new InstanceField().RunTests();
        new LocalVariable().RunTests();
        new StaticFieldStaticInitializer().RunTests();
        new StaticFieldNoInitializer().RunTests();
        Console.ReadLine();
    }
    class InstanceField
    {
        public bool[] arr= new bool[1024];
        public void RunTests()
        {
            var watch = Stopwatch.StartNew();
            int count = 0;
            for (int i = 0; i < 500000; i++)
            {
                for (int j = 0; j < arr.Length; j++)
                {
                    if (arr[j]) count++;
                }
            }
            watch.Stop();
            Console.WriteLine("{0}: {1}ms", GetType().Name, watch.ElapsedMilliseconds);
        }
    }
    class LocalVariable
    {
        public void RunTests()
        {
            bool[] arr = new bool[1024];
            var watch = Stopwatch.StartNew();
            int count = 0;
            for (int i = 0; i < 500000; i++)
            {
                for (int j = 0; j < arr.Length; j++)
                {
                    if (arr[j]) count++;
                }
            }
            watch.Stop();
            Console.WriteLine("{0}: {1}ms", GetType().Name, watch.ElapsedMilliseconds);
        }
    }
    class StaticFieldStaticInitializer
    {
        public static bool[] arr = new bool[1024];
        public void RunTests()
        {
            var watch = Stopwatch.StartNew();
            int count = 0;
            for (int i = 0; i < 500000; i++)
            {
                for (int j = 0; j < arr.Length; j++)
                {
                    if (arr[j]) count++;
                }
            }
            watch.Stop();
            Console.WriteLine("{0}: {1}ms", GetType().Name, watch.ElapsedMilliseconds);
        }
    }
    class StaticFieldNoInitializer
    {
        public static bool[] arr;
        public void RunTests()
        {                
            arr = new bool[1024];
            var watch = Stopwatch.StartNew();
            int count = 0;
            for (int i = 0; i < 500000; i++)
            {
                for (int j = 0; j < arr.Length; j++)
                {
                    if (arr[j]) count++;
                }
            }
            watch.Stop();
            Console.WriteLine("{0}: {1}ms", GetType().Name, watch.ElapsedMilliseconds);
        }
    }
}