summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/utils/search
diff options
context:
space:
mode:
authorGravatar 2xsaiko2020-05-19 08:19:19 +0200
committerGravatar GitHub2020-05-19 02:19:19 -0400
commit2b906a2c19d9c564808d4391be90c84de3b17581 (patch)
tree0e9a72e9a8f6953346b041896c96e8209abc87ef /src/main/java/cuchaz/enigma/utils/search
parentQOL fixes - Volume 2 (#239) (diff)
downloadenigma-fork-2b906a2c19d9c564808d4391be90c84de3b17581.tar.gz
enigma-fork-2b906a2c19d9c564808d4391be90c84de3b17581.tar.xz
enigma-fork-2b906a2c19d9c564808d4391be90c84de3b17581.zip
Async search (#245)
* Async search * Define index when it's used
Diffstat (limited to 'src/main/java/cuchaz/enigma/utils/search')
-rw-r--r--src/main/java/cuchaz/enigma/utils/search/SearchUtil.java73
1 files changed, 73 insertions, 0 deletions
diff --git a/src/main/java/cuchaz/enigma/utils/search/SearchUtil.java b/src/main/java/cuchaz/enigma/utils/search/SearchUtil.java
index e5ed35f..a51afbb 100644
--- a/src/main/java/cuchaz/enigma/utils/search/SearchUtil.java
+++ b/src/main/java/cuchaz/enigma/utils/search/SearchUtil.java
@@ -1,6 +1,12 @@
1package cuchaz.enigma.utils.search; 1package cuchaz.enigma.utils.search;
2 2
3import java.util.*; 3import java.util.*;
4import java.util.concurrent.Executor;
5import java.util.concurrent.Executors;
6import java.util.concurrent.atomic.AtomicBoolean;
7import java.util.concurrent.atomic.AtomicInteger;
8import java.util.concurrent.locks.Lock;
9import java.util.concurrent.locks.ReentrantLock;
4import java.util.function.BiFunction; 10import java.util.function.BiFunction;
5import java.util.stream.Collectors; 11import java.util.stream.Collectors;
6import java.util.stream.Stream; 12import java.util.stream.Stream;
@@ -11,6 +17,7 @@ public class SearchUtil<T extends SearchEntry> {
11 17
12 private final Map<T, Entry<T>> entries = new HashMap<>(); 18 private final Map<T, Entry<T>> entries = new HashMap<>();
13 private final Map<String, Integer> hitCount = new HashMap<>(); 19 private final Map<String, Integer> hitCount = new HashMap<>();
20 private final Executor searchExecutor = Executors.newWorkStealingPool();
14 21
15 public void add(T entry) { 22 public void add(T entry) {
16 Entry<T> e = Entry.from(entry); 23 Entry<T> e = Entry.from(entry);
@@ -46,6 +53,59 @@ public class SearchUtil<T extends SearchEntry> {
46 .sequential(); 53 .sequential();
47 } 54 }
48 55
56 public SearchControl asyncSearch(String term, SearchResultConsumer<T> consumer) {
57 Map<String, Integer> hitCount = new HashMap<>(this.hitCount);
58 Map<T, Entry<T>> entries = new HashMap<>(this.entries);
59 float[] scores = new float[entries.size()];
60 Lock scoresLock = new ReentrantLock();
61 AtomicInteger size = new AtomicInteger();
62 AtomicBoolean control = new AtomicBoolean(false);
63 AtomicInteger elapsed = new AtomicInteger();
64 for (Entry<T> value : entries.values()) {
65 searchExecutor.execute(() -> {
66 try {
67 if (control.get()) return;
68 float score = value.getScore(term, hitCount.getOrDefault(value.searchEntry.getIdentifier(), 0));
69 if (score <= 0) return;
70 score = -score; // sort descending
71 try {
72 scoresLock.lock();
73 if (control.get()) return;
74 int dataSize = size.getAndIncrement();
75 int index = Arrays.binarySearch(scores, 0, dataSize, score);
76 if (index < 0) {
77 index = ~index;
78 }
79 System.arraycopy(scores, index, scores, index + 1, dataSize - index);
80 scores[index] = score;
81 consumer.add(index, value.searchEntry);
82 } finally {
83 scoresLock.unlock();
84 }
85 } finally {
86 elapsed.incrementAndGet();
87 }
88 });
89 }
90
91 return new SearchControl() {
92 @Override
93 public void stop() {
94 control.set(true);
95 }
96
97 @Override
98 public boolean isFinished() {
99 return entries.size() == elapsed.get();
100 }
101
102 @Override
103 public float getProgress() {
104 return (float) elapsed.get() / entries.size();
105 }
106 };
107 }
108
49 public void hit(T entry) { 109 public void hit(T entry) {
50 if (entries.containsKey(entry)) { 110 if (entries.containsKey(entry)) {
51 hitCount.compute(entry.getIdentifier(), (_id, i) -> i == null ? 1 : i + 1); 111 hitCount.compute(entry.getIdentifier(), (_id, i) -> i == null ? 1 : i + 1);
@@ -192,4 +252,17 @@ public class SearchUtil<T extends SearchEntry> {
192 252
193 } 253 }
194 254
255 @FunctionalInterface
256 public interface SearchResultConsumer<T extends SearchEntry> {
257 void add(int index, T entry);
258 }
259
260 public interface SearchControl {
261 void stop();
262
263 boolean isFinished();
264
265 float getProgress();
266 }
267
195} 268}