From b6cab458ed22a7157b6052e77e9421288349f9c7 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Tue, 30 Aug 2016 13:42:29 +0100 Subject: [PATCH] Use a heap instead of sorting to gather the best shell-candidates matches O(n + k * log n) (with k = 100 here) instead of O(n log n), much faster with many candidates. --- src/commands.cc | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/commands.cc b/src/commands.cc index ac64c9c3..e8a26506 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -904,11 +904,20 @@ void define_command(const ParametersParser& parser, Context& context, const Shel if (RankedMatch match{candidate.first, candidate.second, query, query_letters}) matches.push_back(match); } - std::sort(matches.begin(), matches.end()); - matches.erase(std::unique(matches.begin(), matches.end()), matches.end()); + + constexpr size_t max_count = 100; + // Gather best max_count matches + auto greater = [](const RankedMatch& lhs, + const RankedMatch& rhs) { return rhs < lhs; }; + auto first = matches.begin(), last = matches.end(); + std::make_heap(first, last, greater); CandidateList res; - for (auto& m : matches) - res.push_back(m.candidate().str()); + while(res.size() < max_count and first != last) + { + if (res.empty() or res.back() != first->candidate()) + res.push_back(first->candidate().str()); + std::pop_heap(first, last--, greater); + } return Completions{ 0_byte, pos_in_token, std::move(res) }; };