不安全的性能C#,删除长期转换为int以访问数组索引

时间:2011-01-20 09:51:12

标签: c# arrays performance unsafe

您好我在C#unsafe中获得了以下代码,其中数组已修复

array[(int)(index)]

索引很长(由于某些原因必须很长)..所以我需要将它强制转换为int才能访问数组元素。有没有办法在不安全的代码中使用指针或其他一些操作组合来防止这个强制转换原因索引的长值为1(并且永远不会超过int值obv)。 我觉得可能不安全的指针添加可能会阻止它发生。我也觉得这个演员不是免费的......演出是这里的问题。 (正是这一行) 我也认为这是不可能的,但我要求以防我错了。

好的,给出一些更多的细节,我在长的preIndex上做一些必要的逻辑操作,比如

  

value = array [(int)((preIndex& mask)>> 10)]

这些操作是必需的,代码已经非常简约。我只能发现可以优化的是从long转换为int,导致按位操作是必需的。

由于

5 个答案:

答案 0 :(得分:3)

unchecked上下文(默认值)中,强制转换将丢弃不需要的MSB,因此不会降低性能。在检查的上下文中,如果索引范围超过int.MaxValue,它将抛出异常。

答案 1 :(得分:2)

是的,从long转换为int琐碎成本,但我非常确定a:不会在任何理智的代码和b中都很重要:它是不可避免的(数组是通过int索引访问的;句点)。要显示不会重要:

static class Program
{
    static int GetSize() { return 10000; }
    static void Main() {

        int size = GetSize();
        int[] someData = new int[size];

        var watchInt32 = Stopwatch.StartNew();
        for (int i = 0; i < 5000; i++)
        {
            for (int j = 0; j < size; j++)
            {
                someData[j]++;
            }
        }
        for (int j = 0; j < size; j++) someData[j] = 0;
        watchInt32.Stop();
        long lSize = size;
        var watchInt64 = Stopwatch.StartNew();
        for (int i = 0; i < 5000; i++)
        {
            for (long j = 0; j < lSize; j++)
            {
                someData[j]++;
            }
        }
        watchInt64.Stop();

        Console.WriteLine("{0}ms vs {1}ms over {2} iterations",
            (int)watchInt32.ElapsedMilliseconds,
            (int)watchInt64.ElapsedMilliseconds, 5000 * size);
    }
}

我明白了:

  

162ms vs 215ms超过50000次迭代

除非您的代码除了数组访问权限之外没有,否则这根本不重要。完全没有。以任何重要的方式。

答案 2 :(得分:1)

我认为您不必担心转换可能会对性能造成影响。只需查看JIT生成的机器代码,它们对于intlong索引都是相同的:

x86,发布模式,int索引:

        var val = arr[idx];
00000059  cmp         ebx,dword ptr [edx+4] 
0000005c  jae         00000078 
0000005e  mov         esi,dword ptr [edx+ebx*4+8] 


x86,发布模式,已铸造long索引:

        var val = arr[(int)idx];
0000005f  cmp         ebx,dword ptr [edx+4] 
00000062  jae         00000081 
00000064  mov         esi,dword ptr [edx+ebx*4+8]

x64,发布模式,int索引:

        var val = arr[idx];
00000060  movsxd      rcx,ebx 
00000063  mov         rax,qword ptr [rdi+8] 
00000067  cmp         rcx,3 
0000006b  jae         0000000000000080 
0000006d  mov         ecx,dword ptr [rdi+rcx*4+10h] 


x64,发布模式,long索引:

        var val = arr[(int)idx];
00000061  movsxd      rcx,ebx 
00000064  mov         rax,qword ptr [rdi+8] 
00000068  cmp         rcx,3 
0000006c  jae         0000000000000080 
0000006e  mov         ecx,dword ptr [rdi+rcx*4+10h]

Daniel Gehriger指出,机器码中不需要考虑conv.i4 IL指令,只需删除32个MSB。

答案 3 :(得分:-1)

您从该行看到的性能问题来自索引查找 - 它是一个常规数组,如object []?或者你实现了索引属性吗?

答案 4 :(得分:-1)

int count = 10000000;
            object [] a = new object[count];

            Stopwatch s1 = Stopwatch.StartNew();
            for (long i = 0; i < count; i++)
                a[i] = new object();
            s1.Stop();

            Stopwatch s2 = Stopwatch.StartNew();
            for (int i = 0; i < count; i++)
                a[i] = new object();
            s2.Stop();       



            Debug.WriteLine(s1.ElapsedTicks + "  " + s2.ElapsedTicks);
  

3362502 3115428

因此没有重大影响。

相关问题