Browse code

Use threading when matching/scoring

John Hawthorn authored on 18/06/2016 05:56:38
Showing 2 changed files

... ...
@@ -11,20 +11,21 @@ INSTALL=install
11 11
 INSTALL_PROGRAM=$(INSTALL)
12 12
 INSTALL_DATA=${INSTALL} -m 644
13 13
 
14
+LIBS=-lpthread
14 15
 OBJECTS=src/fzy.o src/match.o src/tty.o src/choices.o src/options.o src/tty_interface.o
15 16
 TESTOBJECTS=test/fzytest.c src/match.o src/choices.o
16 17
 
17 18
 all: fzy
18 19
 
19 20
 test/fzytest: $(TESTOBJECTS)
20
-	$(CC) $(CFLAGS) $(CCFLAGS) -Isrc -o $@ $(TESTOBJECTS)
21
+	$(CC) $(CFLAGS) $(CCFLAGS) -Isrc -o $@ $(TESTOBJECTS) $(LIBS)
21 22
 
22 23
 test: check
23 24
 check: test/fzytest
24 25
 	$(DEBUGGER) ./test/fzytest
25 26
 
26 27
 fzy: $(OBJECTS)
27
-	$(CC) $(CFLAGS) $(CCFLAGS) -o $@ $(OBJECTS)
28
+	$(CC) $(CFLAGS) $(CCFLAGS) -o $@ $(OBJECTS) $(LIBS)
28 29
 
29 30
 %.o: %.c config.h
30 31
 	$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
... ...
@@ -134,23 +134,77 @@ size_t choices_available(choices_t *c) {
134 134
 	return c->available;
135 135
 }
136 136
 
137
+#include <pthread.h>
138
+
139
+struct worker {
140
+	pthread_t thread_id;
141
+	choices_t *choices;
142
+	const char *search;
143
+	size_t worker_count;
144
+	size_t worker_num;
145
+	struct scored_result *results;
146
+	size_t available;
147
+};
148
+
149
+static void *choices_search_worker(void *data) {
150
+	struct worker *w = (struct worker *)data;
151
+	const choices_t *c = w->choices;
152
+
153
+	size_t start = (w->worker_num) * c->size / w->worker_count;
154
+	size_t end = (w->worker_num + 1) * c->size / w->worker_count;
155
+
156
+	for(size_t i = start; i < end; i++) {
157
+		if (has_match(w->search, c->strings[i])) {
158
+			w->results[w->available].str = c->strings[i];
159
+			w->results[w->available].score = match(w->search, c->strings[i]);
160
+			w->available++;
161
+		}
162
+	}
163
+
164
+	return w;
165
+}
166
+
137 167
 void choices_search(choices_t *c, const char *search) {
138 168
 	choices_reset_search(c);
139 169
 
170
+	/* allocate storage for our results */
140 171
 	c->results = malloc(c->size * sizeof(struct scored_result));
141 172
 	if (!c->results) {
142 173
 		fprintf(stderr, "Error: Can't allocate memory\n");
143 174
 		abort();
144 175
 	}
145 176
 
146
-	for (size_t i = 0; i < c->size; i++) {
147
-		if (has_match(search, c->strings[i])) {
148
-			c->results[c->available].str = c->strings[i];
149
-			c->results[c->available].score = match(search, c->strings[i]);
150
-			c->available++;
177
+	int worker_count = 8;
178
+	struct worker *workers = calloc(worker_count, sizeof(struct worker));
179
+	for (int i = 0; i < worker_count; i++) {
180
+		workers[i].choices = c;
181
+		workers[i].search = search;
182
+		workers[i].worker_count = worker_count;
183
+		workers[i].worker_num = i;
184
+		workers[i].results = malloc(c->size * sizeof(struct scored_result)); /* FIXME: This is overkill */
185
+		int ret = pthread_create(&workers[i].thread_id, NULL, &choices_search_worker, &workers[i]);
186
+		if (ret != 0) {
187
+			perror("pthread_create");
188
+			exit(EXIT_FAILURE);
151 189
 		}
152 190
 	}
153 191
 
192
+	for (int i = 0; i < worker_count; i++) {
193
+		struct worker *w = &workers[i];
194
+
195
+		int ret = pthread_join(w->thread_id, NULL);
196
+		if (ret != 0) {
197
+			perror("pthread_join");
198
+			exit(EXIT_FAILURE);
199
+		}
200
+
201
+		memcpy(&c->results[c->available], w->results,  w->available * sizeof(struct scored_result));
202
+		c->available += w->available;
203
+
204
+		free(w->results);
205
+	}
206
+	free(workers);
207
+
154 208
 	if(*search) {
155 209
 		qsort(c->results, c->available, sizeof(struct scored_result), cmpchoice);
156 210
 	}