2017-03-09 102 views
12

我目前正在考虑移植我的metro hash implementon以使用C#7功能,因为几个部分可能从ref当地人获益以提高性能。 散列在ulong[4]数组上进行计算,但结果是16 byte数组。目前我正在将ulong数组复制到结果byte缓冲区,但这需要一些时间。 所以我想知道如果System.Runtime.CompilerServices.Unsafe是安全的,在这里使用:Unsafe.As从字节数组到ulong数组

var result = new byte[16]; 
ulong[] state = Unsafe.As<byte[], ulong[]>(ref result); 
ref var firstState = ref state[0]; 
ref var secondState = ref state[1]; 
ulong thirdState = 0; 
ulong fourthState = 0; 

上面的代码片断意味着我使用的结果缓冲区也为我州的计算部分,而不是只对最终输出。

我的单元测试是成功的,根据benchmarkdotnet跳过块复制会导致性能增加,这足以让我发现它是否正确使用它。

+0

欢迎来到这里和第一个问题! –

+3

你在做什么是通过一个结构(这一个http://stackoverflow.com/a/35841815/613130)铸造的旧“诀窍”...如果你检查'state.Length'你会看到这是错误的”。 – xanatos

+2

仍然非常有趣的图书馆,你已经找到:-) – xanatos

回答

1

C#支持 “固定缓冲存储器”,这里的那种东西,我们可以这样做:

public unsafe struct Bytes 
    { 
     public fixed byte bytes[16]; 
    } 

然后

public unsafe static Bytes Convert (long[] longs) 
    { 
     fixed (long * longs_ptr = longs) 
       return *((Bytes*)(longs_ptr)); 
    } 

试试吧。 (C#中原始类型的1D数组总是作为连续的内存块存储,这就是为什么获取(托管)数组的地址很好)。

你也可以甚至返回指针更快的速度:

public unsafe static Bytes * Convert (long[] longs) 
    { 
     fixed (long * longs_ptr = longs) 
     return ((Bytes*)(longs_ptr)); 
    } 

和操作/只要你想访问的字节数。

 var s = Convert(longs); 
     var b = s->bytes[0];