[Rpm-maint] [PATCH 4/5] Optimize readLine routine

Alexey Tourbin alexey.tourbin at gmail.com
Tue Feb 5 04:31:38 UTC 2013


This change introduces the following optimizations:
- Line chunking used to be done with per-character loop; it now uses
  strchr(line, '\n') call.
- Likewise, the "balancing check" has been enhanced with strpbrk(3).

Callgrind annotations for 'rpmspec -P glibc.spec', previous commit:
94,796,525  PROGRAM TOTALS
33,242,383  rpmio/argv.c:argvCount
 9,886,925  build/parseSpec.c:readLine
 3,964,158  glibc-2.16-75f0d304/malloc/malloc.c:_int_malloc
...

Callgrind annotations for 'rpmspec -P glibc.spec', this commit:
88,013,018  PROGRAM TOTALS
33,242,383  rpmio/argv.c:argvCount
 3,964,158  glibc-2.16-75f0d304/malloc/malloc.c:_int_malloc
...
---
 build/parseSpec.c | 66 ++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 38 insertions(+), 28 deletions(-)

diff --git a/build/parseSpec.c b/build/parseSpec.c
index 9429454..6cd6bc0 100644
--- a/build/parseSpec.c
+++ b/build/parseSpec.c
@@ -290,23 +290,30 @@ static int copyNextLineFromOFI(rpmSpec spec, OFI_t *ofi)
 {
     /* Expand next line from file into line buffer */
     if (!(spec->nextline && *spec->nextline)) {
-	int pc = 0, bc = 0, nc = 0;
 	const char *from = ofi->readPtr;
-	char ch = ' ';
-	while (from && *from && ch != '\n') {
-	    ch = spec->lbuf[spec->lbufOff] = *from;
-	    spec->lbufOff++; from++;
-
-	    if (spec->lbufOff >= spec->lbufSize) {
-		spec->lbufSize += BUFSIZ;
-		spec->lbuf = realloc(spec->lbuf, spec->lbufSize);
-	    }
+	const char *end = strchr(from, '\n');
+	size_t len;
+	if (end == NULL) {
+	    len = strlen(from);
+	    end = from + len;
+	}
+	else {
+	    end++; /* grab newline */
+	    len = end - from;
+	}
+	if (len + 1 > spec->lbufSize - spec->lbufOff) {
+	    spec->lbufSize += BUFSIZ + len + 1;
+	    spec->lbuf = xrealloc(spec->lbuf, spec->lbufSize);
 	}
+	memcpy(spec->lbuf + spec->lbufOff, from, len);
+	spec->lbufOff += len;
 	spec->lbuf[spec->lbufOff] = '\0';
-	ofi->readPtr = from;
+	ofi->readPtr = end;
 
 	/* Check if we need another line before expanding the buffer. */
-	for (const char *p = spec->lbuf; *p; p++) {
+	int pc = 0, bc = 0, nc = 0;
+	for (const char *p = spec->lbuf;
+		(p = strpbrk(p, "\\\n%{}()")) != NULL; p++)
 	    switch (*p) {
 		case '\\':
 		    switch (*(p+1)) {
@@ -328,7 +335,6 @@ static int copyNextLineFromOFI(rpmSpec spec, OFI_t *ofi)
 		case '(': if (pc > 0) pc++; break;
 		case ')': if (pc > 0) pc--; break;
 	    }
-	}
 	
 	/* If it doesn't, ask for one more line. */
 	if (pc || bc || nc ) {
@@ -359,22 +365,23 @@ static int copyNextLineFromOFI(rpmSpec spec, OFI_t *ofi)
     return 0;
 }
 
+/* Logical chunking into lines after macro expansion */
 static void copyNextLineFinish(rpmSpec spec, int strip)
 {
-    char *last;
-    char ch;
-
-    /* Find next line in expanded line buffer */
-    spec->line = last = spec->nextline;
-    ch = ' ';
-    while (*spec->nextline && ch != '\n') {
-	ch = *spec->nextline++;
-	if (!risspace(ch))
-	    last = spec->nextline;
+    /* This line is to be processed */
+    spec->line = spec->nextline;
+
+    /* Next line is after newline character */
+    char *end = strchr(spec->line, '\n');
+    if (end == NULL) {
+	/* Last line */
+	size_t len = strlen(spec->line);
+	end = spec->line + len;
+	spec->nextline = end;
     }
-
-    /* Save 1st char of next line in order to terminate current line. */
-    if (*spec->nextline != '\0') {
+    else {
+	spec->nextline = end + 1;
+	/* Save 1st char of next line in order to terminate current line */
 	spec->nextpeekc = *spec->nextline;
 	*spec->nextline = '\0';
     }
@@ -382,8 +389,11 @@ static void copyNextLineFinish(rpmSpec spec, int strip)
     if (strip & STRIP_COMMENTS)
 	handleComments(spec->line);
     
-    if (strip & STRIP_TRAILINGSPACE)
-	*last = '\0';
+    if (strip & STRIP_TRAILINGSPACE) {
+	while (end > spec->line && risspace(end[-1]))
+	    end--;
+	*end = '\0';
+    }
 }
 
 static int readLineFromOFI(rpmSpec spec, OFI_t *ofi)
-- 
1.8.1



More information about the Rpm-maint mailing list