git: a3abf6658334 - stable/12 - grep: replace the internal queue with a ring buffer
Kyle Evans
kevans at FreeBSD.org
Mon Dec 28 03:19:42 UTC 2020
The branch stable/12 has been updated by kevans:
URL: https://cgit.FreeBSD.org/src/commit/?id=a3abf665833465461030c413f07d324e7d64ae30
commit a3abf665833465461030c413f07d324e7d64ae30
Author: Kyle Evans <kevans at FreeBSD.org>
AuthorDate: 2020-12-09 05:27:45 +0000
Commit: Kyle Evans <kevans at FreeBSD.org>
CommitDate: 2020-12-28 03:19:26 +0000
grep: replace the internal queue with a ring buffer
We know up front how many items we can have in the queue (-B/Bflag), so
pay the cost of those particular allocations early on.
The reduced queue maintenance overhead seemed to yield about an ~8%
improvement for my earlier `grep -C8 -r closefrom .` test.
(cherry picked from commit df546c3b730d4abcace1da24226bd5f01280588e)
---
usr.bin/grep/grep.c | 2 +
usr.bin/grep/grep.h | 1 +
usr.bin/grep/queue.c | 127 ++++++++++++++++++++++++++++++---------------------
3 files changed, 78 insertions(+), 52 deletions(-)
diff --git a/usr.bin/grep/grep.c b/usr.bin/grep/grep.c
index 731e46bb112e..a7ecc2015571 100644
--- a/usr.bin/grep/grep.c
+++ b/usr.bin/grep/grep.c
@@ -712,6 +712,8 @@ main(int argc, char *argv[])
if ((aargc == 0 || aargc == 1) && !Hflag)
hflag = true;
+ initqueue();
+
if (aargc == 0 && dirbehave != DIR_RECURSE)
exit(!procfile("-"));
diff --git a/usr.bin/grep/grep.h b/usr.bin/grep/grep.h
index 6d1e87ae4d7c..62e82c7f56b6 100644
--- a/usr.bin/grep/grep.h
+++ b/usr.bin/grep/grep.h
@@ -149,6 +149,7 @@ char *grep_strdup(const char *str);
void grep_printline(struct str *line, int sep);
/* queue.c */
+void initqueue(void);
bool enqueue(struct str *x);
void printqueue(void);
void clearqueue(void);
diff --git a/usr.bin/grep/queue.c b/usr.bin/grep/queue.c
index b5f3aa14f0e2..ac15185f0694 100644
--- a/usr.bin/grep/queue.c
+++ b/usr.bin/grep/queue.c
@@ -6,6 +6,7 @@
*
* Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
* All rights reserved.
+ * Copyright (c) 2020 Kyle Evans <kevans at FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -45,77 +46,99 @@ __FBSDID("$FreeBSD$");
#include "grep.h"
-struct qentry {
- STAILQ_ENTRY(qentry) list;
- struct str data;
-};
+typedef struct str qentry_t;
-static STAILQ_HEAD(, qentry) queue = STAILQ_HEAD_INITIALIZER(queue);
-static long long count;
-
-static struct qentry *dequeue(void);
+static long long filled;
+static qentry_t *qend, *qpool;
/*
- * Enqueue another line; return true if we've dequeued a line as a result
+ * qnext is the next entry to populate. qlist is where the list actually
+ * starts, for the purposes of printing.
*/
-bool
-enqueue(struct str *x)
+static qentry_t *qlist, *qnext;
+
+void
+initqueue(void)
{
- struct qentry *item;
-
- item = grep_malloc(sizeof(struct qentry));
- item->data.dat = grep_malloc(sizeof(char) * x->len);
- item->data.len = x->len;
- item->data.line_no = x->line_no;
- item->data.boff = x->boff;
- item->data.off = x->off;
- memcpy(item->data.dat, x->dat, x->len);
- item->data.file = x->file;
-
- STAILQ_INSERT_TAIL(&queue, item, list);
-
- if (++count > Bflag) {
- item = dequeue();
- free(item->data.dat);
- free(item);
- return (true);
- }
- return (false);
+
+ qlist = qnext = qpool = grep_calloc(Bflag, sizeof(*qpool));
+ qend = qpool + (Bflag - 1);
}
-static struct qentry *
-dequeue(void)
+static qentry_t *
+advqueue(qentry_t *itemp)
{
- struct qentry *item;
- item = STAILQ_FIRST(&queue);
- if (item == NULL)
- return (NULL);
+ if (itemp == qend)
+ return (qpool);
+ return (itemp + 1);
+}
- STAILQ_REMOVE_HEAD(&queue, list);
- --count;
- return (item);
+/*
+ * Enqueue another line; return true if we've dequeued a line as a result
+ */
+bool
+enqueue(struct str *x)
+{
+ qentry_t *item;
+ bool rotated;
+
+ item = qnext;
+ qnext = advqueue(qnext);
+ rotated = false;
+
+ if (filled < Bflag) {
+ filled++;
+ } else if (filled == Bflag) {
+ /* We had already filled up coming in; just rotate. */
+ qlist = advqueue(qlist);
+ rotated = true;
+ free(item->dat);
+ }
+ item->dat = grep_malloc(sizeof(char) * x->len);
+ item->len = x->len;
+ item->line_no = x->line_no;
+ item->boff = x->boff;
+ item->off = x->off;
+ memcpy(item->dat, x->dat, x->len);
+ item->file = x->file;
+
+ return (rotated);
}
void
printqueue(void)
{
- struct qentry *item;
-
- while ((item = dequeue()) != NULL) {
- grep_printline(&item->data, '-');
- free(item->data.dat);
- free(item);
- }
+ qentry_t *item;
+
+ item = qlist;
+ do {
+ /* Buffer must have ended early. */
+ if (item->dat == NULL)
+ break;
+
+ grep_printline(item, '-');
+ free(item->dat);
+ item->dat = NULL;
+ item = advqueue(item);
+ } while (item != qlist);
+
+ qlist = qnext = qpool;
+ filled = 0;
}
void
clearqueue(void)
{
- struct qentry *item;
+ qentry_t *item;
- while ((item = dequeue()) != NULL) {
- free(item->data.dat);
- free(item);
- }
+ item = qlist;
+ do {
+ free(item->dat);
+ item->dat = NULL;
+ item = advqueue(item);
+ } while (item != qlist);
+
+ qlist = qnext = qpool;
+ filled = 0;
}
More information about the dev-commits-src-all
mailing list