From d5561623aab5e6547f258e8165951beae11e94e3 Mon Sep 17 00:00:00 2001
From: Mahmoud Al-Qudsi <mqudsi@neosmart.net>
Date: Fri, 16 Sep 2022 21:35:29 -0500
Subject: [PATCH] Reduce memory allocations for deduping completions

Instead of adding the completions themselves to an `unordered_set` to
see if any are duplicates, just add a reference to the item instead.
---
 src/complete.cpp | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/src/complete.cpp b/src/complete.cpp
index 85d3cba2f..7f4ae7784 100644
--- a/src/complete.cpp
+++ b/src/complete.cpp
@@ -273,12 +273,25 @@ __attribute__((always_inline)) static inline bool compare_completions_by_tilde(
 }
 
 /// Unique the list of completions, without perturbing their order.
-static void unique_completions_retaining_order(completion_list_t *comps) {
-    std::unordered_set<wcstring> seen;
+static void dedup_completions_retaining_order(completion_list_t *comps) {
+    struct ref_hash_t {
+        size_t operator()(const wcstring &val) const {
+            return std::hash<const wcstring>()(val);
+        }
+    };
+
+    struct ref_equal_t {
+        bool operator()(const wcstring &lhs, const wcstring &rhs) const {
+            return lhs == rhs;
+        }
+    };
+
+    std::unordered_set<std::reference_wrapper<const wcstring>, ref_hash_t, ref_equal_t> seen;
     seen.reserve(comps->size());
     auto pred = [&seen](const completion_t &c) {
         // Remove (return true) if insertion fails.
-        bool inserted = seen.insert(c.completion).second;
+        auto r = std::reference_wrapper<const wcstring>(c.completion);
+        bool inserted = seen.insert(r).second;
         return !inserted;
     };
     comps->erase(std::remove_if(comps->begin(), comps->end(), pred), comps->end());
@@ -299,7 +312,7 @@ void completions_sort_and_prioritize(completion_list_t *comps, completion_reques
                  comps->end());
 
     // Deduplicate both sorted and unsorted results.
-    unique_completions_retaining_order(comps);
+    dedup_completions_retaining_order(comps);
 
     // Sort, provided COMPLETE_DONT_SORT isn't set.
     // Here we do not pass suppress_exact, so that exact matches appear first.