Browse code

Read entire input into contiguous memory

This should be slightly faster at loading the input into memory, since
fewer mallocs will be required vs running one malloc per-line of input.

Realloc on modern systems is fast. It can use mremap internally to remap
virtual memory pages and avoid copying. This can be seen in strace. Neat!

I thought that this might be friendlier to caching, but there was no
noticeable differnce when scanning through the strings for matches. It's
probable that the previous strdups placed them more-or-less contiguously
and the extra padding for malloc bookkeeping didn't make a significant
differnce. This also suggests that alignment of the candidate strings
wasn't important.

John Hawthorn authored on 21/04/2016 18:12:15
Showing 1 changed files

  • fzy.c index af45c3b..1578421 100644
... ...
@@ -19,19 +19,34 @@ static size_t scrolloff = 1;
19 19
 static const char *prompt = "> ";
20 20
 
21 21
 static void read_choices(choices_t *c) {
22
-	const char *line;
23
-	char buf[4096];
24
-	while (fgets(buf, sizeof buf, stdin)) {
25
-		char *nl;
26
-		if ((nl = strchr(buf, '\n')))
27
-			*nl = '\0';
28
-
29
-		if (!(line = strdup(buf))) {
30
-			fprintf(stderr, "Cannot allocate memory");
31
-			abort();
32
-		}
33
-		choices_add(c, line);
22
+	size_t bufsize = 65536;
23
+	size_t pos = 0;
24
+	size_t sizeread;
25
+
26
+	/* Read entire file into contiguous memory buffer */
27
+	char *buf = malloc(bufsize);
28
+	while ((sizeread = fread(buf + pos, 1, bufsize - pos, stdin))) {
29
+		pos += sizeread;
30
+		bufsize *= 2;
31
+		buf = realloc(buf, bufsize);
34 32
 	}
33
+	buf = realloc(buf, pos + 1);
34
+
35
+	buf[pos] = 0;
36
+
37
+	/* Tokenize input and add to choices */
38
+	char *line = buf;
39
+	do {
40
+		char *nl = strchr(line, '\n');
41
+		if (nl)
42
+			*nl++ = '\0';
43
+
44
+		/* Skip empty lines */
45
+		if (*line)
46
+			choices_add(c, line);
47
+
48
+		line = nl;
49
+	} while (line);
35 50
 }
36 51
 
37 52
 #define SEARCH_SIZE_MAX 4096