source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mdocml: Make the man(1) and apropos(1) options -s and -S much less
@ 2015-01-20 18:21 schwarze
  0 siblings, 0 replies; only message in thread
From: schwarze @ 2015-01-20 18:21 UTC (permalink / raw)
  To: source

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

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2015-01-20 18:21 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-20 18:21 mdocml: Make the man(1) and apropos(1) options -s and -S much less schwarze

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).