source@mandoc.bsd.lv
 help / color / mirror / Atom feed
From: schwarze@mdocml.bsd.lv
To: source@mdocml.bsd.lv
Subject: mdocml: Make the man(1) and apropos(1) options -s and -S much less
Date: Tue, 20 Jan 2015 13:21:48 -0500 (EST)	[thread overview]
Message-ID: <1131798396323019379.enqueue@fantadrom.bsd.lv> (raw)

Log Message:
-----------
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.216, 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 <theo at math dot ethz dot ch>, thanks!

Modified Files:
--------------
    mdocml:
        mansearch.c

Revision Data
-------------
Index: mansearch.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mansearch.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -Lmansearch.c -Lmansearch.c -u -p -r1.52 -r1.53
--- mansearch.c
+++ mansearch.c
@@ -1,7 +1,7 @@
 /*	$Id$ */
 /*
  * Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -85,7 +85,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 *,
@@ -96,8 +97,6 @@ static	void		*hash_calloc(size_t, size_t
 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,
@@ -343,14 +342,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);
@@ -407,7 +408,8 @@ manpage_compare(const void *vp1, const v
 }
 
 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;
@@ -432,10 +434,15 @@ buildnames(struct manpage *mpage, sqlite
 			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. */
@@ -645,8 +652,7 @@ exprcomp(const struct mansearch *search,
 	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])) {
@@ -712,45 +718,13 @@ exprcomp(const struct mansearch *search,
 
 		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)
 		exprfree(first);
 	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 *
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

                 reply	other threads:[~2015-01-20 18:21 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1131798396323019379.enqueue@fantadrom.bsd.lv \
    --to=schwarze@mdocml.bsd.lv \
    --cc=source@mdocml.bsd.lv \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).