perf(dbviewer): cache filteredHistory.Count once per export
The DB export loop called filteredHistory.Count twice per 5000-message batch — once for the progress fraction, once for the status text. filteredHistory is built lazily by Filter() and re-enumerates on every .Count access, so on a 2M-message history each batch was paying for two full passes through the IEnumerable. Materializing the count once at the top reduces the export to a single O(N) traversal as intended. The RunOnTick + delayTicks pacing is intentional (keeps SeString encoding on the framework thread and rate-limits the export to avoid laggy frames during long exports), so the rest of the loop stays put.
This commit is contained in:
@@ -391,6 +391,10 @@ public class DbViewer : Window
|
||||
await rangeMessageEnumerator.DisposeAsync();
|
||||
|
||||
var filteredHistory = Filter(messageHistory);
|
||||
// Materialize Count once — re-enumerating the IEnumerable on
|
||||
// every batch (twice per batch in the Notification update)
|
||||
// turned the export into an O(N²) hot loop on large histories.
|
||||
var totalCount = filteredHistory.Count;
|
||||
|
||||
var sb = new StringBuilder();
|
||||
await using var stream = new StreamWriter(Path.Join(InputPath, $"Chat2_{DateTime.Now:yyyy_dd_M__HH_mm_ss}.txt"));
|
||||
@@ -416,8 +420,8 @@ public class DbViewer : Window
|
||||
}
|
||||
}, delayTicks: 5);
|
||||
|
||||
Notification.Progress = (float)batch / filteredHistory.Count;
|
||||
Notification.Content = $"Exported {batch} of {filteredHistory.Count} messages";
|
||||
Notification.Progress = (float)batch / totalCount;
|
||||
Notification.Content = $"Exported {batch} of {totalCount} messages";
|
||||
await stream.WriteAsync(sb.ToString());
|
||||
sb.Clear();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user