[Dctrl-tools-devel] [SCM] Debian control file query tools branch, master, updated. 9e8b8b4dcbecdca31d72439c6405fb4fdac7c1e7

Antti-Juhani Kaijanaho ajk at debian.org
Wed Nov 7 20:07:17 UTC 2007


The branch, master has been updated
       via  9e8b8b4dcbecdca31d72439c6405fb4fdac7c1e7 (commit)
      from  7f9cd73cb73427215ecf465a60257df6897c2fe5 (commit)


- Shortlog ------------------------------------------------------------
9e8b8b4 lib/paragraph.c (para_parse_next): Use gotos, not a state variable

Summary of changes:
 debian/changelog |    3 +-
 lib/paragraph.c  |  263 ++++++++++++++++++++++++++----------------------------
 2 files changed, 129 insertions(+), 137 deletions(-)
-----------------------------------------------------------------------
Details of changes:

commit 9e8b8b4dcbecdca31d72439c6405fb4fdac7c1e7
Author: Antti-Juhani Kaijanaho <ajk at debian.org>
Date:   Sat Nov 3 10:05:03 2007 +0200

    lib/paragraph.c (para_parse_next): Use gotos, not a state variable
    
    On modern processors, unconditional jumps are always better than
    conditional jumps.  This rewrite eliminates a set of conditional
    jumps by encoding the states as goto targets and not using a
    while-switch strategy.
    
    Recent simple measurements on several systems show ca. 20 % speedup.
    
    Signed-off-by: Antti-Juhani Kaijanaho <ajk at debian.org>

diff --git a/debian/changelog b/debian/changelog
index ef72f98..55f8f78 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,8 +1,9 @@
 dctrl-tools (2.13) UNRELEASED; urgency=low
 
   * debian/control: suggest debtags, note grep-debtags in description
+  * lib/paragraph (para_parse_next): Performance improvements.
 
- -- Antti-Juhani Kaijanaho <ajk at debian.org>  Sun, 28 Oct 2007 14:07:05 +0200
+ -- Antti-Juhani Kaijanaho <ajk at debian.org>  Sat, 03 Nov 2007 10:03:29 +0200
 
 dctrl-tools (2.12) unstable; urgency=low
 
diff --git a/lib/paragraph.c b/lib/paragraph.c
index b08b537..b5f5903 100644
--- a/lib/paragraph.c
+++ b/lib/paragraph.c
@@ -78,7 +78,6 @@ static struct field_data * register_field(para_t * para,
 void para_parse_next(para_t * para)
 {
 redo:
-	debug_message("para_parse_next", 0);
 	assert(para != 0);
 	para_parser_t * pp = para->common;
 	para->start = pp->loc;
@@ -90,147 +89,139 @@ redo:
 	if (pp->invalidate_p) {
 		fsaf_invalidate(pp->fp, para->start);
 	}
-	register enum { START, FIELD_NAME, BODY, BODY_NEWLINE,
-			BODY_SKIPBLANKS, END, FAIL } state = START;
+
 	register size_t pos = para->start;
 	register size_t line = para->line;
 	register FSAF * fp = pp->fp;
 	size_t field_start = 0;
 	struct field_data * field_data = 0;
-	while (state != END && state != FAIL) {
-#               ifndef TEST_NODEBUG
-		static char * const stnm[] = { "START", "FIELD_NAME",
-					       "BODY", "BODY_NEWLINE",
-					       "BODY_SKIPBLANKS", "END",
-					       "FAIL" };
-		if (do_msg(L_DEBUG)) {
-			fprintf(stderr, "%s:%zu: state: %s\n",
-				fp->fname, line, stnm[state]);
-		}
-#               endif
-		int c = fsaf_getc(fp, pos++);
-		if (c == '\n') line++;
-		switch (state) {
-		case START:
-			switch (c) {
-			case -1:
-				pp->eof = true;
-				state = END;
-				break;
-			case '\n':
-				para->start++;
-				break;
-			default:
-				field_start = --pos;
-				state = FIELD_NAME;
-			}
-			break;
-		case FIELD_NAME:
-			switch (c) {
-			case '\n': case -1:
-				if (pp->ignore_broken_paras) {
-					line_message(L_IMPORTANT,
-						     _("warning: "
-						       "expected a colon"),
-						     fp->fname,
-                                                     c == '\n' ?line-1:line);
-					state = FAIL;
-				} else {
-					line_message(L_FATAL,
-						     _("expected a colon"),
-						     fp->fname,
-                                                     c == '\n' ?line-1:line);
-					fail();
-				}
-				break;
-			case ':': {
-				size_t len = (pos-1) - field_start;
-				struct fsaf_read_rv r = fsaf_read(fp,
-								  field_start,
-								  len);
-				assert(r.len == len);
-				struct field_attr *attr =
-					fieldtrie_lookup(r.b, len);
-				if (attr == NULL) {
-                                        if (para->common->
-                                            register_unknown_fields) {
-                                                field_data =
-                                                        register_field(para,
-                                                                       r.b,
-                                                                       len);
-                                        } else {
-                                                field_data = 0;
-                                        }
-				} else {
-					assert(attr->inx < para->nfields);
-					field_data = &para->fields[attr->inx];
-                                }
-                                if (field_data != NULL) {
-					field_data->start = pos;
-					field_data->line = line;
-				}
-				state = BODY;
-			}
-				break;
-			}
-			break;
-		case BODY:
-			if (c == -1 || c == '\n') {
-				if (field_data != 0) {
-					field_data->end = pos-1;
-					while (field_data->start < field_data->end
-					       && fsaf_getc(fp, field_data->start)
-					       == ' ') {
-						++field_data->start;
-					}
-				}
-				state = BODY_NEWLINE;
-			}
-			if (c != -1) break;
-			/* conditional passthrough */
-		case BODY_NEWLINE:
-			switch (c) {
-			case -1:
-				//para->eof = true;
-				/* pass through */
-			case '\n':
-				state = END;
-				break;
-			case ' ': case '\t':
-				state = BODY_SKIPBLANKS;
-				break;
-			default:
-				field_start = --pos;
-				state = FIELD_NAME;
-			}
-			break;
-		case BODY_SKIPBLANKS:
-			switch (c) {
-			case -1:
-				/* pass through */
-			case '\n':
-				state = END;
-				break;
-			case ' ': case '\t':
-				break;
-			default:
-				state = BODY;
-			}
-			break;
-		default: assert(0);
-		}
-	}
+
+#define GETC (c = fsaf_getc(fp, pos++), c == '\n' ? line++ : line)
+        int c;
+START:
+        GETC;
+        switch (c) {
+        case -1:
+                pp->eof = true;
+                goto END;
+        case '\n':
+                para->start++;
+                goto START;
+        default:
+                field_start = --pos;
+                goto FIELD_NAME;
+        }
+        assert(0);
+
+FIELD_NAME:
+        GETC;
+        switch (c) {
+        case '\n': case -1:
+                if (pp->ignore_broken_paras) {
+                        line_message(L_IMPORTANT,
+                                     _("warning: expected a colon"),
+                                     fp->fname,
+                                     c == '\n' ?line-1:line);
+                        goto FAIL;
+                } else {
+                        line_message(L_FATAL,
+                                     _("expected a colon"),
+                                     fp->fname,
+                                     c == '\n' ?line-1:line);
+                        fail();
+                }
+                break;
+        case ':': {
+                size_t len = (pos-1) - field_start;
+                struct fsaf_read_rv r = fsaf_read(fp,
+                                                  field_start,
+                                                  len);
+                assert(r.len == len);
+                struct field_attr *attr =
+                        fieldtrie_lookup(r.b, len);
+                if (attr == NULL) {
+                        if (para->common->
+                            register_unknown_fields) {
+                                field_data =
+                                        register_field(para,
+                                                       r.b,
+                                                       len);
+                        } else {
+                                field_data = 0;
+                        }
+                } else {
+                        assert(attr->inx < para->nfields);
+                        field_data = &para->fields[attr->inx];
+                }
+                if (field_data != NULL) {
+                        field_data->start = pos;
+                        field_data->line = line;
+                }
+                goto BODY;
+        }
+        default:
+                goto FIELD_NAME;
+        }
+        assert(0);
+
+BODY:
+        GETC;
+        if (c == -1 || c == '\n') {
+                if (field_data != 0) {
+                        field_data->end = pos-1;
+                        while (field_data->start < field_data->end
+                               && fsaf_getc(fp, field_data->start)
+                               == ' ') {
+                                ++field_data->start;
+                        }
+                }
+                goto BODY_NEWLINE;
+        }
+        if (c != -1) goto BODY; else goto BODY_NEWLINE;
+        assert(0);
+
+BODY_NEWLINE:
+        GETC;
+        switch (c) {
+        case -1:
+                //para->eof = true;
+                /* pass through */
+        case '\n':
+                goto END;
+        case ' ': case '\t':
+                goto BODY_SKIPBLANKS;
+        default:
+                field_start = --pos;
+		goto FIELD_NAME;
+        }
+        assert(0);
+
+BODY_SKIPBLANKS:
+        GETC;
+        switch (c) {
+        case -1:
+                /* pass through */
+        case '\n':
+                goto END;
+                break;
+        case ' ': case '\t':
+                goto BODY_SKIPBLANKS;
+        default:
+                goto BODY;
+        }
+        assert(0);
+
+#undef GETC
+
+FAIL:
+        do {
+                c = fsaf_getc(fp, pp->loc++);
+                if (c == '\n') pp->line++;
+        } while (c != -1 && c != '\n');
+        goto redo;
+
+END:
 	para->end = pos-1;
 	pp->loc = para->end;
 	pp->line = fsaf_getc(fp, pp->loc) == '\n' ? line-1 : line;
-
-	if (state == FAIL) {
-		/* skip the rest of the broken line */
-		int c;
-		do {
-			c = fsaf_getc(fp, pp->loc++);
-			if (c == '\n') pp->line++;
-		} while (c != -1 && c != '\n');
-		goto redo;
-	}
 }

-- 
Debian control file query tools



More information about the Dctrl-tools-devel mailing list