diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2014-04-10 02:46:21 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2014-04-10 02:46:21 +0000 |
commit | 27c8079fded40c4d4345acd5aee489d29bb14470 (patch) | |
tree | e2eccdc323d9c95cd629e5621b52e6da2a29eeda /mansearch.c | |
parent | fd8475f993a8cff7151b0ad852febee4632f4d57 (diff) | |
download | mandoc-27c8079fded40c4d4345acd5aee489d29bb14470.tar.gz mandoc-27c8079fded40c4d4345acd5aee489d29bb14470.tar.zst mandoc-27c8079fded40c4d4345acd5aee489d29bb14470.zip |
Next speed optimization step for the new apropos(1).
Split manual names out of the common "keys" table into their
own "names" table. This reduces standard apropos(1) search
times (i.e. searching for names and descriptions only) by
typically about 70% for the full /usr/share/man database.
(Yes, that multiplies with the previous optimization step,
so both together have reduced search times by a factor of
more than six. I'm not done yet, expect more to come.)
Even with the minimal databases built with makewhatis(8) -Q,
this step still reduces search times by 15-20%. For both cases,
database sizes and build times hardly change (+/-2%).
Diffstat (limited to 'mansearch.c')
-rw-r--r-- | mansearch.c | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/mansearch.c b/mansearch.c index 3d070026..b2c7fe6d 100644 --- a/mansearch.c +++ b/mansearch.c @@ -1,4 +1,4 @@ -/* $Id: mansearch.c,v 1.26 2014/04/09 21:50:08 schwarze Exp $ */ +/* $Id: mansearch.c,v 1.27 2014/04/10 02:46:21 schwarze Exp $ */ /* * Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org> @@ -221,7 +221,7 @@ mansearch(const struct mansearch *search, SQL_BIND_BLOB(db, s, j, ep->regexp); } else SQL_BIND_TEXT(db, s, j, ep->substr); - if (0 == (TYPE_Nd & ep->bits)) + if (0 == ((TYPE_Nd | TYPE_Nm) & ep->bits)) SQL_BIND_INT64(db, s, j, ep->bits); } @@ -504,6 +504,12 @@ sql_statement(const struct expr *e) ? (NULL == e->substr ? "desc REGEXP ?" : "desc MATCH ?") + : TYPE_Nm == e->bits + ? (NULL == e->substr + ? "id IN (SELECT pageid FROM names " + "WHERE name REGEXP ?)" + : "id IN (SELECT pageid FROM names " + "WHERE name MATCH ?)") : (NULL == e->substr ? "id IN (SELECT pageid FROM keys " "WHERE key REGEXP ? AND bits & ?)" @@ -525,8 +531,9 @@ sql_statement(const struct expr *e) static struct expr * exprcomp(const struct mansearch *search, int argc, char *argv[]) { + uint64_t mask; int i, toopen, logic, igncase, toclose; - struct expr *first, *next, *cur; + struct expr *first, *prev, *cur, *next; first = cur = NULL; logic = igncase = toclose = 0; @@ -569,6 +576,7 @@ exprcomp(const struct mansearch *search, int argc, char *argv[]) first = next; else cur->next = next; + prev = cur = next; /* * Searching for descriptions must be split out @@ -576,18 +584,23 @@ exprcomp(const struct mansearch *search, int argc, char *argv[]) * not in the keys table. */ - if (TYPE_Nd & next->bits && ~TYPE_Nd & next->bits) { - cur = mandoc_calloc(1, sizeof(struct expr)); - memcpy(cur, next, sizeof(struct expr)); - next->open = 1; - next->bits = TYPE_Nd; - next->next = cur; - cur->bits &= ~TYPE_Nd; + for (mask = TYPE_Nm; mask <= TYPE_Nd; mask <<= 1) { + if (mask & cur->bits && ~mask & cur->bits) { + next = mandoc_calloc(1, + sizeof(struct expr)); + memcpy(next, cur, sizeof(struct expr)); + prev->open = 1; + cur->bits = mask; + cur->next = next; + cur = next; + cur->bits &= ~mask; + } + } + prev->and = (1 == logic); + prev->open += toopen; + if (cur != prev) cur->close = 1; - } else - cur = next; - next->and = (1 == logic); - next->open += toopen; + toopen = logic = igncase = 0; } if (toopen || logic || igncase || toclose) |