Skip to content

Implement performance optimizations and caching improvements#567

Open
Hirogen wants to merge 23 commits intoDevelopmentfrom
logfilereaderOptimisations
Open

Implement performance optimizations and caching improvements#567
Hirogen wants to merge 23 commits intoDevelopmentfrom
logfilereaderOptimisations

Conversation

@Hirogen
Copy link
Copy Markdown
Collaborator

@Hirogen Hirogen commented Apr 16, 2026

This pull request introduces significant performance and memory optimizations to the log buffer infrastructure, improves thread safety, and enhances code robustness with better null checking and minor API cleanups. The most notable changes are a complete refactoring of how log lines are stored and managed in LogBuffer, the introduction of a buffer pool for efficient reuse, and improvements to utility methods for safer usage.

Log buffer and memory management improvements:

  • Refactored LogBuffer to use a pooled array (LogLine[] rented from ArrayPool<LogLine>) instead of a List<ILogLineMemory>, reducing heap allocations and improving performance for large log files. Added Reinitialise and thread-safe locking methods, and changed AddLine/GetLineMemoryOfBlock to operate on the new structure. [1] [2]
  • Introduced LogBufferPool for efficient pooling and reuse of LogBuffer instances, further reducing memory churn and allocation overhead.

API and type safety improvements:

  • Changed LogLine from a class to a readonly record struct, making it a value type for better performance and immutability. Updated documentation accordingly.

Thread safety and concurrency:

  • Added a SpinLock for protecting access to buffer content in LogBuffer, with explicit acquire/release methods.
  • Updated LogBufferCacheEntry to use an atomic field for LastUseTimeStamp with Interlocked operations, ensuring thread-safe access.

Robustness and utility improvements:

  • Made Util a static class and added null checks to all utility methods (GetNameFromPath, StripExtension, GetExtension, and YetiLevenshtein), preventing possible NullReferenceExceptions. Enhanced YetiLevenshtein with fast paths for empty or identical strings. [1] [2] [3] [4] [5]

Documentation and minor cleanups:

  • Improved and clarified XML documentation for configuration properties and removed obsolete/unused code. [1] [2] [3]
  • Minor code cleanups, such as removing unnecessary regions and updating field initializations. [1] [2]

These changes collectively improve the performance, reliability, and maintainability of the log processing core.

@Hirogen Hirogen linked an issue Apr 16, 2026 that may be closed by this pull request
Comment thread src/LogExpert.Tests/BufferShiftTest.cs Fixed
Comment thread src/LogExpert.Tests/BufferShiftTest.cs Fixed
var line = logBuffer.GetLineMemoryOfBlock(0);
Assert.That(line.FullLine.Span.Contains(enumerator.Current.AsSpan(), StringComparison.Ordinal));
#pragma warning disable CS8629 // Nullable value type may be null.
Assert.That(line.Value.FullLine.Span.Contains(enumerator.Current.AsSpan(), StringComparison.Ordinal));
Comment thread src/LogExpert.Tests/BufferShiftTest.cs Fixed
Comment thread src/tools/LogRotator/LogRotator.cs Outdated

// Create initial set of files
Console.WriteLine($"Creating initial files in '{Path.GetFullPath(baseDir)}'...");
WriteLogFile(Path.Combine(baseDir, baseName), 0);
Comment thread src/tools/LogRotator/LogRotator.cs Outdated

for (var i = 1; i <= maxBackups; i++)
{
WriteLogFile(Path.Combine(baseDir, $"{baseName}.{i}"), i);
Comment thread src/tools/LogRotator/LogRotator.cs Outdated
Console.WriteLine($"\n--- Rotation #{rotationCount} ---");

// Delete the oldest file (simulates maxBackups limit)
var oldest = Path.Combine(baseDir, $"{baseName}.{maxBackups}");
Comment thread src/tools/LogRotator/LogRotator.cs Outdated
// Shift all numbered files up by one
for (var i = maxBackups - 1; i >= 1; i--)
{
var src = Path.Combine(baseDir, $"{baseName}.{i}");
Comment thread src/tools/LogRotator/LogRotator.cs Outdated
for (var i = maxBackups - 1; i >= 1; i--)
{
var src = Path.Combine(baseDir, $"{baseName}.{i}");
var dst = Path.Combine(baseDir, $"{baseName}.{i + 1}");
Comment thread src/tools/LogRotator/LogRotator.cs Outdated
}

// Rename current log to .1
var current = Path.Combine(baseDir, baseName);
var line = logBuffer.GetLineMemoryOfBlock(0);
Assert.That(line.FullLine.Span.Contains(enumerator.Current.AsSpan(), StringComparison.Ordinal));
Assert.That(line.HasValue, Is.True);
Assert.That(line.Value.FullLine.Span.Contains(enumerator.Current.AsSpan(), StringComparison.Ordinal));
BRUNER Patrick and others added 6 commits April 16, 2026 21:31
Introduce LineOffsetIndex for efficient line start tracking and
MemoryMappedFileReader for fast, scalable log file access using
memory-mapped files. Supports tail mode and random line access,
improving performance for large and growing log files.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Font issues

1 participant