Skip to content

Commit 5040622

Browse files
author
BRUNER Patrick
committed
update reader
1 parent 90ef20b commit 5040622

11 files changed

Lines changed: 415 additions & 717 deletions

src/LogExpert.Benchmarks/StreamReaderBenchmarks.cs

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,6 @@ public void System_ReadAll_Small ()
8787
ReadAllLines(reader);
8888
}
8989

90-
[Benchmark]
91-
public void Channel_ReadAll_Small ()
92-
{
93-
using var stream = new MemoryStream(_smallTestData);
94-
using var reader = new PositionAwareStreamReaderChannel(stream, new EncodingOptions(), 10000);
95-
ReadAllLines(reader);
96-
}
97-
9890
[Benchmark]
9991
public void Pipeline_ReadAll_Small ()
10092
{
@@ -119,14 +111,6 @@ public void System_ReadAll_Medium ()
119111
ReadAllLines(reader);
120112
}
121113

122-
[Benchmark]
123-
public void Channel_ReadAll_Medium ()
124-
{
125-
using var stream = new MemoryStream(_mediumTestData);
126-
using var reader = new PositionAwareStreamReaderChannel(stream, new EncodingOptions(), 10000);
127-
ReadAllLines(reader);
128-
}
129-
130114
[Benchmark]
131115
public void Pipeline_ReadAll_Medium ()
132116
{
@@ -151,14 +135,6 @@ public void System_ReadAll_Large ()
151135
ReadAllLines(reader);
152136
}
153137

154-
[Benchmark]
155-
public void Channel_ReadAll_Large ()
156-
{
157-
using var stream = new MemoryStream(_largeTestData);
158-
using var reader = new PositionAwareStreamReaderChannel(stream, new EncodingOptions(), 10000);
159-
ReadAllLines(reader);
160-
}
161-
162138
[Benchmark]
163139
public void Pipeline_ReadAll_Large ()
164140
{
@@ -175,14 +151,6 @@ public void Pipeline_ReadAll_Unicode ()
175151
ReadAllLines(reader);
176152
}
177153

178-
[Benchmark]
179-
public void Channel_ReadAll_Unicode ()
180-
{
181-
using var stream = new MemoryStream(_unicodeTestData);
182-
using var reader = new PositionAwareStreamReaderChannel(stream, new EncodingOptions { Encoding = Encoding.UTF8 }, 10000);
183-
ReadAllLines(reader);
184-
}
185-
186154
[Benchmark]
187155
public void Pipeline_Seek_And_Read ()
188156
{
@@ -202,25 +170,6 @@ public void Pipeline_Seek_And_Read ()
202170
ReadAllLines(reader);
203171
}
204172

205-
[Benchmark]
206-
public void Channel_Seek_And_Read ()
207-
{
208-
using var stream = new MemoryStream(_mediumTestData);
209-
using var reader = new PositionAwareStreamReaderChannel(stream, new EncodingOptions(), 10000);
210-
211-
// Read first 100 lines
212-
for (int i = 0; i < 100; i++)
213-
{
214-
_ = reader.ReadLine();
215-
}
216-
217-
// Seek back to beginning
218-
reader.Position = 0;
219-
220-
// Read all lines
221-
ReadAllLines(reader);
222-
}
223-
224173
private static void ReadAllLines (ILogStreamReader reader)
225174
{
226175
while (reader.ReadLine() != null)
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
using System.Collections.Concurrent;
2+
3+
using LogExpert.Core.EventArguments;
4+
5+
namespace LogExpert.Core.Classes.Log;
6+
7+
/// <summary>
8+
/// Batches progress updates to reduce UI thread marshalling overhead.
9+
/// Collects updates in a thread-safe queue and processes them on a timer.
10+
/// </summary>
11+
public sealed class BatchedProgressReporter : IDisposable
12+
{
13+
private readonly ConcurrentQueue<LoadFileEventArgs> _progressQueue = new();
14+
private readonly System.Threading.Timer _timer;
15+
private readonly Action<LoadFileEventArgs> _progressCallback;
16+
private readonly int _updateIntervalMs;
17+
private bool _disposed;
18+
19+
/// <summary>
20+
/// Creates a new batched progress reporter.
21+
/// </summary>
22+
/// <param name="progressCallback">Callback to invoke with latest progress</param>
23+
/// <param name="updateIntervalMs">Update interval in milliseconds (default: 100ms)</param>
24+
public BatchedProgressReporter (Action<LoadFileEventArgs> progressCallback, int updateIntervalMs = 100)
25+
{
26+
_progressCallback = progressCallback ?? throw new ArgumentNullException(nameof(progressCallback));
27+
_updateIntervalMs = updateIntervalMs;
28+
29+
// Start timer
30+
_timer = new Timer(ProcessQueue, null, updateIntervalMs, updateIntervalMs);
31+
}
32+
33+
/// <summary>
34+
/// Reports progress (thread-safe, non-blocking)
35+
/// </summary>
36+
public void ReportProgress (LoadFileEventArgs args)
37+
{
38+
if (_disposed)
39+
{
40+
return;
41+
}
42+
43+
// Only keep the latest update - discard old ones
44+
_progressQueue.Enqueue(args);
45+
46+
// Keep queue size bounded (max 10 items)
47+
while (_progressQueue.Count > 10)
48+
{
49+
_ = _progressQueue.TryDequeue(out _);
50+
}
51+
}
52+
53+
/// <summary>
54+
/// Flushes any pending updates immediately
55+
/// </summary>
56+
public void Flush ()
57+
{
58+
ProcessQueue(null);
59+
}
60+
61+
private void ProcessQueue (object state)
62+
{
63+
if (_disposed)
64+
{
65+
return;
66+
}
67+
68+
// Get only the LATEST update (discard intermediate ones)
69+
LoadFileEventArgs latestUpdate = null;
70+
while (_progressQueue.TryDequeue(out var update))
71+
{
72+
latestUpdate = update;
73+
}
74+
75+
// Invoke callback with latest update
76+
if (latestUpdate != null)
77+
{
78+
try
79+
{
80+
_progressCallback(latestUpdate);
81+
}
82+
catch (Exception ex)
83+
{
84+
// Log but don't crash
85+
System.Diagnostics.Debug.WriteLine($"Error in progress callback: {ex.Message}");
86+
}
87+
}
88+
}
89+
90+
public void Dispose ()
91+
{
92+
if (_disposed)
93+
{
94+
return;
95+
}
96+
97+
_disposed = true;
98+
99+
Flush();
100+
_timer?.Dispose();
101+
102+
// Clear queue
103+
_progressQueue.Clear();
104+
}
105+
}

0 commit comments

Comments
 (0)