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();
|
await rangeMessageEnumerator.DisposeAsync();
|
||||||
|
|
||||||
var filteredHistory = Filter(messageHistory);
|
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();
|
var sb = new StringBuilder();
|
||||||
await using var stream = new StreamWriter(Path.Join(InputPath, $"Chat2_{DateTime.Now:yyyy_dd_M__HH_mm_ss}.txt"));
|
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);
|
}, delayTicks: 5);
|
||||||
|
|
||||||
Notification.Progress = (float)batch / filteredHistory.Count;
|
Notification.Progress = (float)batch / totalCount;
|
||||||
Notification.Content = $"Exported {batch} of {filteredHistory.Count} messages";
|
Notification.Content = $"Exported {batch} of {totalCount} messages";
|
||||||
await stream.WriteAsync(sb.ToString());
|
await stream.WriteAsync(sb.ToString());
|
||||||
sb.Clear();
|
sb.Clear();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user