2026-07-24 10:42:18 +08:00

85 lines
2.5 KiB
C#

namespace BuildFlow.Workflow.Tests.Performance;
/// <summary>记录读取次数、总字节数和单次最大读取请求的只读测试流。</summary>
public sealed class TrackingReadStream(Stream inner) : Stream
{
/// <summary>累计实际读取字节数。</summary>
public long BytesRead { get; private set; }
/// <summary>累计读取调用次数。</summary>
public int ReadCalls { get; private set; }
/// <summary>单次读取请求的最大缓冲区长度。</summary>
public int MaxRequestedReadSize { get; private set; }
public override bool CanRead => inner.CanRead;
public override bool CanSeek => inner.CanSeek;
public override bool CanWrite => false;
public override long Length => inner.Length;
public override long Position
{
get => inner.Position;
set => inner.Position = value;
}
public override void Flush() => inner.Flush();
public override int Read(byte[] buffer, int offset, int count)
{
RecordRequest(count);
var read = inner.Read(buffer, offset, count);
BytesRead += read;
return read;
}
public override int Read(Span<byte> buffer)
{
RecordRequest(buffer.Length);
var read = inner.Read(buffer);
BytesRead += read;
return read;
}
public override async ValueTask<int> ReadAsync(
Memory<byte> buffer,
CancellationToken cancellationToken = default)
{
RecordRequest(buffer.Length);
var read = await inner.ReadAsync(buffer, cancellationToken);
BytesRead += read;
return read;
}
public override async Task<int> ReadAsync(
byte[] buffer,
int offset,
int count,
CancellationToken cancellationToken)
{
RecordRequest(count);
var read = await inner.ReadAsync(buffer.AsMemory(offset, count), cancellationToken);
BytesRead += read;
return read;
}
public override long Seek(long offset, SeekOrigin origin) => inner.Seek(offset, origin);
public override void SetLength(long value) => throw new NotSupportedException();
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
protected override void Dispose(bool disposing)
{
if (disposing)
{
inner.Dispose();
}
base.Dispose(disposing);
}
private void RecordRequest(int count)
{
ReadCalls++;
MaxRequestedReadSize = Math.Max(MaxRequestedReadSize, count);
}
}