微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么访问静态数组参考要比非静态数组参考慢

如何解决为什么访问静态数组参考要比非静态数组参考慢

|| 看看这个片段:
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
}
与我直接使用ToggleableLatinChars相比,此代码可证明在测试中更快(7%ish)。 (在该方法中,使用本地引用ToggleableLatinChars的速度也相同)。 仅当针对.NET 4进行编译时,才会注意到这种效果。 当为.NET 3.5编译时,我看到相反的效果-使用静态数组明显更快。 (我的机器是运行Windows 7 64位的Intel i5,并且正在针对x86进行编译) 知道为什么吗? 更新: 这是一个完整的代码示例,与marc的测试示例更相似。注意我现在正在使用静态和局部变量版本(不再是成员变量)。尽管我看到的差异少于我最初的测试代码所看到的差异,但是为.NET 4编译时,本地版本总是更快。您可以交换运行顺序,但是Local总是对我有利。 (针对.NET 3.5进行的编译不会这样做:它比.NET 4的运行速度要快得多,而静态的速度要快得多或相同)
using System;
using System.Diagnostics;
using System.Globalization;

internal class Program
{
    const int RepeatCount = 500000;

    const string TestString1_Unicode =          @\"?=3.1415926?!! ?a??!#!%# ÜBERGRößEN!!?????? ??????@!e=2.71828182?#!!$@\\^i^/!@$\";
    const string TestString2_Numbers =          @\"p=3.14159265358979323846264338327950288419716939937510....!!!!\";
    const string TestString3_LowerCase =        @\"nevr un-den-erstimate ze pauer of stoopid piplz in larg grupp!\\*^*/\";
    const string TestString4_UpperCase =        @\"DUDE,WHY U R HERE?? U SHOULDA BE IN THE MEETING (BLAH-BLAH) $\\*o*/$!\";

    static void Main()
    {

        RunTestsstaticAccess();
        RunTestsLocalAccess();

        Console.ReadLine();
    }

    public static void RunTestsLocalAccess()
    {
        StringToggler st = new StringToggler();

        var watch = Stopwatch.StartNew();
        for (int i = 0; i < RepeatCount; i++)
        {
            st.ToggleCase_LocalAccess(TestString1_Unicode);
            st.ToggleCase_LocalAccess(TestString2_Numbers);
            st.ToggleCase_LocalAccess(TestString3_LowerCase);
            st.ToggleCase_LocalAccess(TestString4_UpperCase);
        }
        watch.Stop();
        Console.WriteLine(\"{0}: {1}ms\",\"RunTestsLocalAccess\",watch.ElapsedMilliseconds);
    }

    public static void RunTestsstaticAccess()
    {
        StringToggler st = new StringToggler();

        var watch = Stopwatch.StartNew();
        for (int i = 0; i < RepeatCount; i++)
        {
            st.ToggleCase_StaticAccess(TestString1_Unicode);
            st.ToggleCase_StaticAccess(TestString2_Numbers);
            st.ToggleCase_StaticAccess(TestString3_LowerCase);
            st.ToggleCase_StaticAccess(TestString4_UpperCase);
        }
        watch.Stop();
        Console.WriteLine(\"{0}: {1}ms\",\"RunTestsstaticAccess\",watch.ElapsedMilliseconds);
    }

    public class StringToggler
    {
        static readonly bool[] ToggleableLatinChars = new[]
        {
            false,false,true,false
        };

        readonly TextInfo textInfo;

        public StringToggler()
        {
            textInfo = CultureInfo.CurrentCulture.TextInfo;
        }

        public StringToggler(CultureInfo cultureInfo)
        {
            textInfo = cultureInfo.TextInfo;
        }

        public unsafe string ToggleCase_StaticAccess(string s)
        {
            s = string.copy(s);

            fixed(char* p = s)
            {
                for (int i = 0; i < s.Length; i++)
                {
                    char ch = p[i];

                    if (ch <= 0xff)
                    {
                        if (ToggleableLatinChars[(byte) ch])
                        {
                            p[i] = (char) (ch ^ 0x20);
                        }
                    }
                    else
                    {
                        switch (CharUnicodeInfo.GetUnicodeCategory(ch))
                        {
                            case UnicodeCategory.UppercaseLetter:
                                p[i] = textInfo.ToLower(ch);
                                break;

                            case UnicodeCategory.LowercaseLetter:
                                p[i] = textInfo.toupper(ch);
                                break;
                        }
                    }
                }
            }

            return s;
        }

        public unsafe string ToggleCase_LocalAccess(string s)
        {
            s = string.copy(s);

            var toggleableLatinChars = ToggleableLatinChars;

            fixed(char* p = s)
            {
                for (int i = 0; i < s.Length; i++)
                {
                    char ch = p[i];

                    if (ch <= 0xff)
                    {
                        if (toggleableLatinChars[(byte) ch])
                        {
                            p[i] = (char) (ch ^ 0x20);
                        }
                    }
                    else
                    {
                        switch (CharUnicodeInfo.GetUnicodeCategory(ch))
                        {
                            case UnicodeCategory.UppercaseLetter:
                                p[i] = textInfo.ToLower(ch);
                                break;

                            case UnicodeCategory.LowercaseLetter:
                                p[i] = textInfo.toupper(ch);
                                break;
                        }
                    }
                }
            }

            return s;
        }
    }
}
    

解决方法

        简单地说:不是。我不信任您(未提供)的测试: 我的结果:
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\",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\",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\",watch.ElapsedMilliseconds);
        }
    }
}
    

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。