私はバイナリデータを読み込む必要がある非常に大きなファイルがある状況に遭遇しました。より速い(安全でない)BinaryReader in .NET
したがって、.NETのデフォルトのBinaryReaderの実装がかなり遅いことに気付きました。 .NET Reflectorでそれを見ている時に私はこれに出くわした:コンピュータは32ビットCPUが発明されて以来32ビット値で動作するように設計された方法で考えて、非常に非効率的なとして私を打つ
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));
}
を。私はオフ時間5-7秒をオフに剃ることに成功し、それを読むために取った - はるかに高速され
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));
}
}
...
}
は:
は、だから私は、代わりにこのようなコードで自分の(危険な)FastBinaryReaderクラスを作りました500 のMBファイルですが、全体的にかなり遅いです(最初は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に欠陥があると判断しました。以下の回答と私自身の解答(解答あり)をご覧ください。
参考になるかもしれません:http://stackoverflow.com/questions/19558435/what-is-the-best-buffer-size-when-using-binaryreader-to-read-big-files-1gb/19837238? noredirect = 1#19837238 –