我一直在尝试一些.NET功能(即管道,内存和阵列池)以实现高速文件读取/解析。在玩client.on('guildMemberAdd', member => {
,Array.Copy
和Buffer.BlockCopy
时遇到了一些有趣的事情。 IO管道将数据读取为ReadOnlySequence.CopyTo
,而我正试图将其有效地转换为byte
。
在玩char
时,我发现我能够从Array.Copy
复制到byte[]
,并且编译器(和运行时)非常乐意这样做。
char[]
此代码可以按预期运行,尽管我确定有些UTF边缘情况在此处未得到正确处理。
我的好奇心来自char[] outputBuffer = ArrayPool<char>.Shared.Rent(inputBuffer.Length);
Array.Copy(buffer, 0, outputBuffer, 0, buffer.Length);
Buffer.BlockCopy
char[] outputBuffer = ArrayPool<char>.Shared.Rent(inputBuffer.Length);
Buffer.BlockCopy(buffer, 0, outputBuffer, 0, buffer.Length);
的结果内容是垃圾。例如,将outputBuffer
的示例内容设置为
buffer
复制后的{ 50, 48, 49, 56, 45 }
的内容是
outputBuffer
我只是好奇CLR内部“幕后”正在发生什么,这导致这两个命令输出了不同的结果。
答案 0 :(得分:12)
Array.Copy()在元素类型方面更聪明。如果可能,将尝试使用memmove()CRT函数。但是会退回到一个循环,在不能循环时复制每个元素。根据需要对其进行转换,它考虑了装箱和原始类型转换。因此,源数组中的一个元素将成为目标数组中的一个元素。
Buffer.BlockCopy()跳过所有内容,并使用memmove()爆炸。不考虑任何转化。这就是为什么它可以稍微快一点的原因。而且更容易误导您有关阵列内容的信息。请注意,utf8编码的字符数据在该数组中可见,12338 == 0x3032 =“ 2”,14385 = 0x3831 =“ 18”,依此类推。使用调试> Windows>内存>内存1更容易查看。
值得注意的是,这种类型强制是的一个功能。说一下,当您通过套接字或管道接收到int []时,却将数据保存在byte []缓冲区中。到目前为止,最快的方法。