gpt4 book ai didi

c# - .NET 中更快(不安全)的 BinaryReader

转载 作者:IT王子 更新时间:2023-10-29 04:23:56 25 4
gpt4 key购买 nike

我遇到过这样一种情况,我有一个很大的文件需要从中读取二进制数据。

因此,我意识到 .NET 中的默认 BinaryReader 实现非常慢。用 .NET Reflector 查看它我遇到了这个:

public virtual int ReadInt32()
{
if (this.m_isMemoryStream)
{
MemoryStream stream = this.m_stream as MemoryStream;
return stream.InternalReadInt32();
}
this.FillBuffer(4);
return (((this.m_buffer[0] | (this.m_buffer[1] << 8)) | (this.m_buffer[2] << 0x10)) | (this.m_buffer[3] << 0x18));
}

自从 32 位 CPU 被发明以来,想想计算机是如何设计为使用 32 位值的,这让我觉得效率极低。

所以我用这样的代码创建了自己的(不安全的)FastBinaryReader 类:

public unsafe class FastBinaryReader :IDisposable
{
private static byte[] buffer = new byte[50];
//private Stream baseStream;

public Stream BaseStream { get; private set; }
public FastBinaryReader(Stream input)
{
BaseStream = input;
}


public int ReadInt32()
{
BaseStream.Read(buffer, 0, 4);

fixed (byte* numRef = &(buffer[0]))
{
return *(((int*)numRef));
}
}
...
}

这要快得多 - 我设法将读取 500 MB 文件所需的时间缩短了 5-7 秒,但总体而言仍然很慢(最初为 29 秒,现在使用我的 FastBinaryReader 约 22 秒)。

我仍然有点困惑为什么读取这么小的文件仍然需要这么长时间。如果我将文件从一个磁盘复制到另一个磁盘,只需几秒钟,因此磁盘吞吐量不是问题。

我进一步内联了 ReadInt32 等调用,最后得到了这段代码:

using (var br = new FastBinaryReader(new FileStream(cacheFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, 0x10000, FileOptions.SequentialScan)))

while (br.BaseStream.Position < br.BaseStream.Length)
{
var doc = DocumentData.Deserialize(br);
docData[doc.InternalId] = doc;
}
}

   public static DocumentData Deserialize(FastBinaryReader reader)
{
byte[] buffer = new byte[4 + 4 + 8 + 4 + 4 + 1 + 4];
reader.BaseStream.Read(buffer, 0, buffer.Length);

DocumentData data = new DocumentData();
fixed (byte* numRef = &(buffer[0]))
{
data.InternalId = *((int*)&(numRef[0]));
data.b = *((int*)&(numRef[4]));
data.c = *((long*)&(numRef[8]));
data.d = *((float*)&(numRef[16]));
data.e = *((float*)&(numRef[20]));
data.f = numRef[24];
data.g = *((int*)&(numRef[25]));
}
return data;
}

关于如何使它更快的任何进一步的想法?我在想也许我可以使用编码将整个文件直接映射到内存中的某些自定义结构之上,因为数据是线性的、固定大小和顺序的。

已解决:我得出的结论是 FileStream 的缓冲/BufferedStream 存在缺陷。请在下面查看已接受的答案和我自己的答案(以及解决方案)。

最佳答案

我在使用 BinaryReader/FileStream 时遇到了类似的性能问题,在分析之后,我发现问题不在于 FileStream 缓冲,而在于这一行:

while (br.BaseStream.Position < br.BaseStream.Length) {

具体来说,FileStream 上的属性 br.BaseStream.Length 进行(相对)缓慢的系统调用以在每个循环中获取文件大小。将代码更改为:

long length = br.BaseStream.Length;
while (br.BaseStream.Position < length) {

并为 FileStream 使用适当的缓冲区大小,我实现了与 MemoryStream 示例类似的性能。

关于c# - .NET 中更快(不安全)的 BinaryReader,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1238388/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com