perf(dbviewer): dispatch FTS filter to worker thread
FullTextSearch + LoadByGuids could stall the draw thread for 100-300 ms on large databases with a popular search term. The two hot trigger sites (FTS toggle, search input) now route via TriggerFilterRefresh, which dispatches the FTS path to Task.Run; the in-memory page-filter path stays inline because it is sub-ms on the loaded page array. _ftsFilterSeq is bumped per trigger so a late worker recognises itself as stale and drops its result instead of overwriting a newer one. The date/channel and history workers already lived on Task.Run and are untouched. Surfaced during the v1.4.8 pre-tag review.
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using Dalamud.Bindings.ImGui;
|
using Dalamud.Bindings.ImGui;
|
||||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
@@ -44,6 +45,10 @@ public class DbViewer : Window
|
|||||||
|
|
||||||
private bool IsProcessing;
|
private bool IsProcessing;
|
||||||
private long ProcessingStart = Environment.TickCount64;
|
private long ProcessingStart = Environment.TickCount64;
|
||||||
|
|
||||||
|
// Bumped per trigger so a late worker drops itself instead of overwriting
|
||||||
|
// a newer result.
|
||||||
|
private long _ftsFilterSeq;
|
||||||
private (DateTime Min, DateTime Max, int Page, bool Local, int ChannelCount) LastProcessed;
|
private (DateTime Min, DateTime Max, int Page, bool Local, int ChannelCount) LastProcessed;
|
||||||
|
|
||||||
private string MinDateString = "";
|
private string MinDateString = "";
|
||||||
@@ -249,7 +254,7 @@ public class DbViewer : Window
|
|||||||
using (ImRaii.Disabled(!ftsReady))
|
using (ImRaii.Disabled(!ftsReady))
|
||||||
{
|
{
|
||||||
if (ImGui.Checkbox(HellionStrings.DbViewer_FullTextToggle, ref UseFullTextSearch))
|
if (ImGui.Checkbox(HellionStrings.DbViewer_FullTextToggle, ref UseFullTextSearch))
|
||||||
Filtered = Filter(Messages);
|
TriggerFilterRefresh();
|
||||||
}
|
}
|
||||||
ImGuiUtil.HelpMarker(
|
ImGuiUtil.HelpMarker(
|
||||||
ftsReady
|
ftsReady
|
||||||
@@ -267,7 +272,7 @@ public class DbViewer : Window
|
|||||||
30
|
30
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
Filtered = Filter(Messages);
|
TriggerFilterRefresh();
|
||||||
|
|
||||||
// Third row
|
// Third row
|
||||||
|
|
||||||
@@ -471,6 +476,34 @@ public class DbViewer : Window
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FTS path hits SQLite per keystroke -- dispatch to a worker, drop stale
|
||||||
|
// results via _ftsFilterSeq. Page-filter path is in-memory LINQ, stays
|
||||||
|
// inline.
|
||||||
|
private void TriggerFilterRefresh()
|
||||||
|
{
|
||||||
|
if (!UseFullTextSearch || !Plugin.MessageManager.Store.IsFtsIndexBuilt)
|
||||||
|
{
|
||||||
|
Filtered = Filter(Messages);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var snapshot = Messages;
|
||||||
|
var mySeq = Interlocked.Increment(ref _ftsFilterSeq);
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = Filter(snapshot);
|
||||||
|
if (Interlocked.Read(ref _ftsFilterSeq) == mySeq)
|
||||||
|
Filtered = result;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Plugin.LogProxy.Error(ex, "FTS filter worker failed");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private ConcurrentStack<Message> Filter(Message[] messages)
|
private ConcurrentStack<Message> Filter(Message[] messages)
|
||||||
{
|
{
|
||||||
if (SimpleSearchTerm == "")
|
if (SimpleSearchTerm == "")
|
||||||
|
|||||||
Reference in New Issue
Block a user