Skip to content

Commit dfbbf7f

Browse files
committed
readstdin: reduce memory-usage by duplicating the line from getline()
Improves upon commit 32db2b1 The getline() implementation often uses a more greedy way of allocating memory. Using this buffer directly and forcing an allocation (by setting it to NULL) would waste a bit of extra space, depending on the implementation of course. Tested on musl libc and glibc. The current glibc version allocates a minimum of 120 bytes per line. For smaller lines musl libc seems less wasteful but still wastes a few bytes per line. On a dmenu_path listing on my system the memory usage was about 350kb (old) vs 30kb (new) on Void Linux glibc. Side-note that getline() also reads NUL bytes in lines, while strdup() would read until the NUL byte. Since dmenu reads text lines either is probably fine(tm). Also rename junk to linesiz.
1 parent ba1a347 commit dfbbf7f

File tree

1 file changed

+5
-4
lines changed

1 file changed

+5
-4
lines changed

dmenu.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -550,21 +550,22 @@ static void
550550
readstdin(void)
551551
{
552552
char *line = NULL;
553-
size_t i, junk, itemsiz = 0;
553+
size_t i, itemsiz = 0, linesiz = 0;
554554
ssize_t len;
555555

556556
/* read each line from stdin and add it to the item list */
557-
for (i = 0; (len = getline(&line, &junk, stdin)) != -1; i++) {
557+
for (i = 0; (len = getline(&line, &linesiz, stdin)) != -1; i++) {
558558
if (i + 1 >= itemsiz) {
559559
itemsiz += 256;
560560
if (!(items = realloc(items, itemsiz * sizeof(*items))))
561561
die("cannot realloc %zu bytes:", itemsiz * sizeof(*items));
562562
}
563563
if (line[len - 1] == '\n')
564564
line[len - 1] = '\0';
565-
items[i].text = line;
565+
if (!(items[i].text = strdup(line)))
566+
die("strdup:");
567+
566568
items[i].out = 0;
567-
line = NULL; /* next call of getline() allocates a new line */
568569
}
569570
free(line);
570571
if (items)

0 commit comments

Comments
 (0)