From c3111de599d926c99918c3939d6ae1008b4f5bb8 Mon Sep 17 00:00:00 2001 From: schwarze Date: Tue, 20 Jan 2015 18:19:39 +0000 Subject: [PATCH] Make the man(1) and apropos(1) options -s and -S much less expensive: Do not append an SQL clause looking into the large "keys" table. Instead, filter the result of the SQL query in buildnames() where equivalent data from the much smaller "mlinks" table is already available for free. This is relevant because man(1) uses the equivalent of "-S ${MACHINE}" by default since main.c rev. 1.122, to make sure that manuals for the current architecture are shown. With many ports installed, this patch can speed up man(1) by a factor of more than a hundred. Slowness reported by Theo Buehler , thanks! --- usr.bin/mandoc/mansearch.c | 72 ++++++++++++-------------------------- 1 file changed, 23 insertions(+), 49 deletions(-) diff --git a/usr.bin/mandoc/mansearch.c b/usr.bin/mandoc/mansearch.c index bc052b3e5e9..2e7c7bd57ed 100644 --- a/usr.bin/mandoc/mansearch.c +++ b/usr.bin/mandoc/mansearch.c @@ -1,7 +1,7 @@ -/* $OpenBSD: mansearch.c,v 1.39 2014/12/06 01:22:28 schwarze Exp $ */ +/* $OpenBSD: mansearch.c,v 1.40 2015/01/20 18:19:39 schwarze Exp $ */ /* * Copyright (c) 2012 Kristaps Dzonsons - * Copyright (c) 2013, 2014 Ingo Schwarze + * Copyright (c) 2013, 2014, 2015 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -77,7 +77,8 @@ struct match { int form; /* bit field: formatted, zipped? */ }; -static void buildnames(struct manpage *, sqlite3 *, +static void buildnames(const struct mansearch *, + struct manpage *, sqlite3 *, sqlite3_stmt *, uint64_t, const char *, int form); static char *buildoutput(sqlite3 *, sqlite3_stmt *, @@ -88,8 +89,6 @@ static void *hash_calloc(size_t, size_t, void *); static struct expr *exprcomp(const struct mansearch *, int, char *[]); static void exprfree(struct expr *); -static struct expr *exprspec(struct expr *, uint64_t, - const char *, const char *); static struct expr *exprterm(const struct mansearch *, char *, int); static int manpage_compare(const void *, const void *); static void sql_append(char **sql, size_t *sz, @@ -335,14 +334,16 @@ mansearch(const struct mansearch *search, mpage->bits = mp->bits; mpage->sec = 10; mpage->form = mp->form; - buildnames(mpage, db, s, mp->pageid, + buildnames(search, mpage, db, s, mp->pageid, paths->paths[i], mp->form); - mpage->output = TYPE_Nd & outbit ? - mp->desc : outbit ? - buildoutput(db, s2, mp->pageid, outbit) : NULL; - + if (mpage->names != NULL) { + mpage->output = TYPE_Nd & outbit ? + mp->desc : outbit ? + buildoutput(db, s2, mp->pageid, outbit) : + NULL; + cur++; + } free(mp); - cur++; } sqlite3_finalize(s); @@ -399,7 +400,8 @@ manpage_compare(const void *vp1, const void *vp2) } static void -buildnames(struct manpage *mpage, sqlite3 *db, sqlite3_stmt *s, +buildnames(const struct mansearch *search, struct manpage *mpage, + sqlite3 *db, sqlite3_stmt *s, uint64_t pageid, const char *path, int form) { char *newnames, *prevsec, *prevarch; @@ -424,10 +426,15 @@ buildnames(struct manpage *mpage, sqlite3 *db, sqlite3_stmt *s, sep1 = ", "; } - /* Fetch the next name. */ + /* Fetch the next name, rejecting sec/arch mismatches. */ sec = (const char *)sqlite3_column_text(s, 0); + if (search->sec != NULL && strcasecmp(sec, search->sec)) + continue; arch = (const char *)sqlite3_column_text(s, 1); + if (search->arch != NULL && *arch != '\0' && + strcasecmp(arch, search->arch)) + continue; name = (const char *)sqlite3_column_text(s, 2); /* Remember the first section found. */ @@ -637,8 +644,7 @@ exprcomp(const struct mansearch *search, int argc, char *argv[]) struct expr *first, *prev, *cur, *next; first = cur = NULL; - logic = igncase = toclose = 0; - toopen = NULL != search->sec || NULL != search->arch; + logic = igncase = toopen = toclose = 0; for (i = 0; i < argc; i++) { if (0 == strcmp("(", argv[i])) { @@ -704,17 +710,8 @@ exprcomp(const struct mansearch *search, int argc, char *argv[]) toopen = logic = igncase = 0; } - if (toopen || logic || igncase || toclose) - goto fail; - - if (NULL != search->sec || NULL != search->arch) - cur->close++; - if (NULL != search->arch) - cur = exprspec(cur, TYPE_arch, search->arch, "^(%s|any)$"); - if (NULL != search->sec) - exprspec(cur, TYPE_sec, search->sec, "^%s$"); - - return(first); + if ( ! (toopen || logic || igncase || toclose)) + return(first); fail: if (NULL != first) @@ -722,29 +719,6 @@ fail: return(NULL); } -static struct expr * -exprspec(struct expr *cur, uint64_t key, const char *value, - const char *format) -{ - char errbuf[BUFSIZ]; - char *cp; - int irc; - - mandoc_asprintf(&cp, format, value); - cur->next = mandoc_calloc(1, sizeof(struct expr)); - cur = cur->next; - cur->and = 1; - cur->bits = key; - if (0 != (irc = regcomp(&cur->regexp, cp, - REG_EXTENDED | REG_NOSUB | REG_ICASE))) { - regerror(irc, &cur->regexp, errbuf, sizeof(errbuf)); - fprintf(stderr, "regcomp: %s\n", errbuf); - cur->substr = value; - } - free(cp); - return(cur); -} - static struct expr * exprterm(const struct mansearch *search, char *buf, int cs) { -- 2.20.1