-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Closed
Labels
area-System.IOhelp wanted[up-for-grabs] Good issue for external contributors[up-for-grabs] Good issue for external contributorstenet-performancePerformance related issuePerformance related issue
Milestone
Description
Description
When BinaryReader.PeekChar is called multiple times for BufferedStream it will cause read of full buffer with each call.
Sample reproduce:
public class CustomStream : Stream {
private readonly FileStream _fileStream;
public CustomStream(FileStream fileStream) {
_fileStream = fileStream;
}
public override int Read(byte[] buffer, int offset, int count) {
Console.WriteLine("Read: count: {0}, pos: {1}, len: {2}, off: {3}", count, Position, Length, offset);
return _fileStream.Read(buffer, offset, count);
}
// other methods are skipped for brevity
}
static void Main(string[] args) {
using var input = new BinaryReader(new BufferedStream(new CustomStream(File.Open("test.rtf", FileMode.Open))));
for (int i = 0; i < 3; i++) {
input.PeekChar();
}
}Running that code will output:
Read: count: 4096, pos: 0, len: 55355, off: 0
Read: count: 4096, pos: 0, len: 55355, off: 0
Read: count: 4096, pos: 0, len: 55355, off: 0
It shows that underlying stream is called to read full buffer (in our case 4096 is a default buffer, but with bigger buffer size it becomes even more prominent)
Analysis
From what I see, the issue occurs when PeekChar restores it's position:
long origPos = _stream.Position;
int ch = Read();
_stream.Position = origPos;and setting Position in BufferedStream resets data in read buffer:
if (_writePos > 0)
FlushWrite();
_readPos = 0;
_readLen = 0; // <-- resetting read buffer
_stream!.Seek(value, SeekOrigin.Begin);Metadata
Metadata
Assignees
Labels
area-System.IOhelp wanted[up-for-grabs] Good issue for external contributors[up-for-grabs] Good issue for external contributorstenet-performancePerformance related issuePerformance related issue