perf(console): extend the filtered view incrementally
With any console filter on, each batch of new output rescanned all N lines to rebuild the visible set. A text filter lowercase-copied the needle and every line to test it: O(total characters) and 2N allocations per batch. When the filter is unchanged and the model only appended or evicted lines since the last pass, the visible indices drop the evicted lines and shift down, and only the new lines are tested. The result equals a full rescan, since line text and channel never change and the filtered view has no folds. A filter change, Clear, or a model window that doesn't follow on from the last one still rescans. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -5858,6 +5858,35 @@ void testConsoleWrapCache()
|
||||
}
|
||||
}
|
||||
|
||||
// ExtendFlatVisibleIndices (console_output_model.h): the incremental filtered visible set equals a full rescan.
|
||||
void testConsoleFlatVisibleIndices()
|
||||
{
|
||||
using dragonx::ui::ExtendFlatVisibleIndices;
|
||||
std::deque<std::string> mdl;
|
||||
std::uint64_t first = 0;
|
||||
auto passes = [&mdl](int i) { return mdl[static_cast<std::size_t>(i)].find('x') != std::string::npos; };
|
||||
auto rescan = [&]() {
|
||||
std::vector<int> v;
|
||||
for (int i = 0; i < static_cast<int>(mdl.size()); ++i) if (passes(i)) v.push_back(i);
|
||||
return v;
|
||||
};
|
||||
for (int i = 0; i < 20; ++i) mdl.push_back(i % 3 == 0 ? "x" + std::to_string(i) : std::string("y"));
|
||||
std::vector<int> vis = rescan();
|
||||
std::uint64_t oldFirst = first, oldEnd = first + mdl.size();
|
||||
for (int k = 0; k < 4; ++k) { mdl.pop_front(); ++first; } // evict 4 (incl. matches 0 and 3)
|
||||
for (int i = 20; i < 25; ++i) mdl.push_back(i % 2 == 0 ? "x" : "y"); // append 5
|
||||
EXPECT_TRUE(ExtendFlatVisibleIndices(vis, oldFirst, oldEnd, first, static_cast<int>(mdl.size()), passes));
|
||||
EXPECT_TRUE(vis == rescan());
|
||||
const std::vector<int> untouched = vis; // non-chaining window => refused
|
||||
EXPECT_FALSE(ExtendFlatVisibleIndices(vis, first, first + mdl.size(), first + mdl.size() + 1, 3, passes));
|
||||
EXPECT_TRUE(vis == untouched);
|
||||
oldFirst = first; oldEnd = first + mdl.size(); // clear(): firstSeq jumps to old end
|
||||
first += mdl.size();
|
||||
mdl.clear(); mdl.push_back("x"); mdl.push_back("y");
|
||||
EXPECT_TRUE(ExtendFlatVisibleIndices(vis, oldFirst, oldEnd, first, static_cast<int>(mdl.size()), passes));
|
||||
EXPECT_TRUE(vis == rescan());
|
||||
}
|
||||
|
||||
// ConsoleScrollController — auto-scroll state machine (pin, wheel-up cooldown, backlog).
|
||||
void testConsoleScrollController()
|
||||
{
|
||||
@@ -15098,6 +15127,7 @@ int main()
|
||||
testDaemonLifecycleAdapters();
|
||||
testConsoleTextLayout();
|
||||
testConsoleWrapCache();
|
||||
testConsoleFlatVisibleIndices();
|
||||
testConsoleModel();
|
||||
testPortfolioHelpers();
|
||||
testMarketSeries();
|
||||
|
||||
Reference in New Issue
Block a user