您好我在C#unsafe中获得了以下代码,其中数组已修复
array[(int)(index)]
索引很长(由于某些原因必须很长)..所以我需要将它强制转换为int才能访问数组元素。有没有办法在不安全的代码中使用指针或其他一些操作组合来防止这个强制转换原因索引的长值为1(并且永远不会超过int值obv)。 我觉得可能不安全的指针添加可能会阻止它发生。我也觉得这个演员不是免费的......演出是这里的问题。 (正是这一行) 我也认为这是不可能的,但我要求以防我错了。
好的,给出一些更多的细节,我在长的preIndex上做一些必要的逻辑操作,比如
value = array [(int)((preIndex& mask)>> 10)]
这些操作是必需的,代码已经非常简约。我只能发现可以优化的是从long转换为int,导致按位操作是必需的。
由于
答案 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生成的机器代码,它们对于int
和long
索引都是相同的:
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
因此没有重大影响。