From a8e99b26535aef9f6c659ce6e1dfc9e19e44f459 Mon Sep 17 00:00:00 2001 From: Andrey Loskutov Date: Tue, 24 Sep 2024 11:24:36 +0200 Subject: [PATCH] File search: cache getMatchCount() result to avoid UI hangs If the search view has matches for 100.000 files, it would hang forever on updating the view via F5 because it asks getMatchCount() for every element and that traverses entire result again and again. This change remembers last computed result and returns that value if there were no further changes on the search result itself. See https://github.com/eclipse-platform/eclipse.platform.ui/issues/2279 --- .../search/ui/text/AbstractTextSearchResult.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/bundles/org.eclipse.search/newsearch/org/eclipse/search/ui/text/AbstractTextSearchResult.java b/bundles/org.eclipse.search/newsearch/org/eclipse/search/ui/text/AbstractTextSearchResult.java index bd9ec3711b6..bffdd573fd6 100644 --- a/bundles/org.eclipse.search/newsearch/org/eclipse/search/ui/text/AbstractTextSearchResult.java +++ b/bundles/org.eclipse.search/newsearch/org/eclipse/search/ui/text/AbstractTextSearchResult.java @@ -44,6 +44,7 @@ public abstract class AbstractTextSearchResult implements ISearchResult { private final ConcurrentMap> fElementsToMatches; private final List fListeners; private final MatchEvent fMatchEvent; + private volatile int matchCount; private MatchFilter[] fMatchFilters; @@ -157,6 +158,7 @@ private MatchEvent getSearchResultEvent(Collection matches, int eventKind private boolean didAddMatch(Match match) { updateFilterState(match); + matchCount = -1; return fElementsToMatches.computeIfAbsent(match.getElement(), k -> ConcurrentHashMap.newKeySet()).add(match); } @@ -178,6 +180,7 @@ public void removeAll() { fireChange(new RemoveAllEvent(this)); } private void doRemoveAll() { + matchCount = 0; fElementsToMatches.clear(); } @@ -216,6 +219,7 @@ public void removeMatches(Match[] matches) { private boolean didRemoveMatch(Match match) { boolean[] existed = new boolean[1]; + matchCount = -1; fElementsToMatches.computeIfPresent(match.getElement(), (f, matches) -> { existed[0] = matches.remove(match); if (matches.isEmpty()) { @@ -302,10 +306,14 @@ private boolean updateFilterState(Match match) { * @return total number of matches */ public int getMatchCount() { - int count = 0; + int count = matchCount; + if (count != -1) { + return count; + } for (Set element : fElementsToMatches.values()) { count += element.size(); } + matchCount = count; return count; }