Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/LogExpert.Core/Classes/Log/LogfileReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1709,8 +1709,8 @@ private ILogStreamReader CreateLogStreamReader (Stream stream, EncodingOptions e
ReaderType.Legacy => new PositionAwareStreamReaderLegacy(stream, encodingOptions, _maximumLineLength),
ReaderType.System => new PositionAwareStreamReaderSystem(stream, encodingOptions, _maximumLineLength),
ReaderType.SystemDirect => new PositionAwareStreamReaderDirect(stream, encodingOptions, _maximumLineLength),
//Default will be System
_ => new PositionAwareStreamReaderSystem(stream, encodingOptions, _maximumLineLength),
//Default will be SystemDirect, because it is the best performing reader and should be used if not explicitly overridden by user.
_ => new PositionAwareStreamReaderDirect(stream, encodingOptions, _maximumLineLength),
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,15 @@ public List<char[]> DetachBlocks ()

// Rent a fresh block and carry over any unscanned data (partial line in progress)
var tailLength = _readBlockLength - _scanOffset;
var newBlock = ArrayPool<char>.Shared.Rent(BLOCK_SIZE);

// The tail may exceed BLOCK_SIZE after reading a long line (buffer was grown).
var newBlockSize = BLOCK_SIZE;
while (tailLength > newBlockSize)
{
newBlockSize *= 2;
}

var newBlock = ArrayPool<char>.Shared.Rent(newBlockSize);

if (tailLength > 0)
{
Expand All @@ -183,8 +191,17 @@ private void RefillBlock (StreamReader reader)
{
var tailLength = _readBlockLength - _scanOffset;

// Rent a new block
var newBlock = ArrayPool<char>.Shared.Rent(BLOCK_SIZE);
// Determine new block size: if the tail already fills a standard block,
// grow the buffer so there's room to read more data. This handles lines
// longer than BLOCK_SIZE (e.g. huge XML payloads).
var newBlockSize = BLOCK_SIZE;
while (tailLength >= newBlockSize)
{
newBlockSize *= 2;
}

// Rent a new block (may be larger than BLOCK_SIZE for very long lines)
var newBlock = ArrayPool<char>.Shared.Rent(newBlockSize);

// Copy the tail (partial line) to the start of the new block
if (tailLength > 0)
Expand All @@ -199,7 +216,8 @@ private void RefillBlock (StreamReader reader)
_scanOffset = 0;

// Fill the rest of the block from the stream
var charsRead = reader.Read(newBlock, tailLength, BLOCK_SIZE - tailLength);
var available = newBlock.Length - tailLength;
var charsRead = reader.Read(newBlock, tailLength, available);

_readBlockLength = tailLength + charsRead;

Expand Down
13 changes: 4 additions & 9 deletions src/LogExpert.Core/Enums/ReaderType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ namespace LogExpert.Core.Enums;
public enum ReaderType
{
/// <summary>
/// System.IO.Pipelines based reader implementation (high performance).
/// Direct-read implementation: reads decoded chars directly into pooled blocks via
/// StreamReader.Read(char[], offset, count), eliminating per-line string allocation.
/// </summary>
Pipeline,
SystemDirect,

/// <summary>
/// Legacy reader implementation (original).
Expand All @@ -18,11 +19,5 @@ public enum ReaderType
/// <summary>
/// System.IO.StreamReader based implementation.
/// </summary>
System,

/// <summary>
/// Direct-read implementation: reads decoded chars directly into pooled blocks via
/// StreamReader.Read(char[], offset, count), eliminating per-line string allocation.
/// </summary>
SystemDirect
System
}
Loading
Loading