diff --git a/src/ui/windows/market_tab.cpp b/src/ui/windows/market_tab.cpp index 9c90fb5..948bd0e 100644 --- a/src/ui/windows/market_tab.cpp +++ b/src/ui/windows/market_tab.cpp @@ -660,7 +660,13 @@ static void pfDrawAddressSection(App* app) } ImGui::Dummy(ImVec2(0, Layout::spacingXs())); std::string search = s_pfEdit.search; - std::vector filtered; + // Selected-address set, built once (membership test for the sort flag and the per-row check below). + std::unordered_set selSet(s_pfEdit.addrs.begin(), s_pfEdit.addrs.end()); + // Each candidate carries its "selected" flag, looked up ONCE (the old comparator did two hash lookups per + // comparison). Same keys + same comparison outcomes => std::sort yields the same permutation as before. + struct PfPick { const AddressInfo* a; bool sel; }; + std::vector filtered; + filtered.reserve(state.addresses.size()); for (const auto& a : state.addresses) { if (s_pfEdit.typeFilter == 1 && a.type != "shielded") continue; if (s_pfEdit.typeFilter == 2 && a.type != "transparent") continue; @@ -669,20 +675,15 @@ static void pfDrawAddressSection(App* app) std::string hay = a.address + " " + app->getAddressLabel(a.address); if (!util::containsIgnoreCase(hay, search)) continue; } - filtered.push_back(&a); + filtered.push_back({&a, selSet.count(a.address) != 0}); } - // Build the selected-address set once — the sort comparator and the per-row membership test below - // both consulted it via a linear PortfolioEntryContains scan (O(n) each) every frame. - std::unordered_set selSet(s_pfEdit.addrs.begin(), s_pfEdit.addrs.end()); - std::sort(filtered.begin(), filtered.end(), [&](const AddressInfo* x, const AddressInfo* y) { - bool sx = selSet.count(x->address) != 0; - bool sy = selSet.count(y->address) != 0; - if (sx != sy) return sx; - return x->balance > y->balance; + std::sort(filtered.begin(), filtered.end(), [](const PfPick& x, const PfPick& y) { + if (x.sel != y.sel) return x.sel; + return x.a->balance > y.a->balance; }); if (selAllClicked) - for (const AddressInfo* a : filtered) - if (data::PortfolioEntryAdd(s_pfEdit.addrs, a->address)) selSet.insert(a->address); + for (const PfPick& p : filtered) + if (data::PortfolioEntryAdd(s_pfEdit.addrs, p.a->address)) selSet.insert(p.a->address); ImGui::Dummy(ImVec2(0, Layout::spacingXs())); ImDrawList* ldl = material::BeginFadeScrollChild("##pfAddrList", s_pfEdit.addrFade, ImVec2(Layout::spacingMd(), Layout::spacingSm()), dp); @@ -690,8 +691,8 @@ static void pfDrawAddressSection(App* app) float lw = ImGui::GetContentRegionAvail().x; if (filtered.empty()) Type().textColored(TypeStyle::Caption, OnSurfaceDisabled(), TR("portfolio_no_addr_match")); - for (const AddressInfo* ap : filtered) { - const AddressInfo& a = *ap; + for (const PfPick& pk : filtered) { + const AddressInfo& a = *pk.a; bool inSet = selSet.count(a.address) != 0; ImVec2 rmn = ImGui::GetCursorScreenPos(); ImVec2 rmx(rmn.x + lw, rmn.y + rowH);