[Rpm-maint] [PATCH 3/5] Optimize expandMacro function
Alexey Tourbin
alexey.tourbin at gmail.com
Tue Feb 5 04:31:37 UTC 2013
From: Alexey Tourbin <at at altlinux.ru>
This change brings the following optimizations:
- In the beginning of the routine, the input string needs to be copied
only in non-terminated case.
- When mb->buf is NULL, expensive xcalloc call is replaced with xmalloc.
It suffices to ensure that mb->buf is (initially) null-terminated at
mb->tpos, and that mbAppend* routines follow this rule.
- The inner per-character loop is replaced with call to strchr(s, '%').
Also note that the "trailing %" case is no longer handled by this part
of the code (this is now the case of no valid macro name).
- New routine mbAppendMem now complements mbAppendStr. Also, mbGrow
routine was factored to improve possibilities for inlining.
Callgrind annotations for 'rpmspec -P selinux-policy.spec', previous commit:
160,979,831 PROGRAM TOTALS
58,348,925 rpmio/argv.c:argvCount
14,378,832 build/parseSpec.c:readLine
10,710,181 glibc-2.16-75f0d304/string/../sysdeps/x86_64/memset.S:__GI_memset
5,445,134 rpmio/macro.c:mbAppend
5,147,651 glibc-2.16-75f0d304/malloc/malloc.c:_int_malloc
3,490,055 rpm-4.10.2/lib/header.c:copyData
...
Callgrind annotations for 'rpmspec -P selinux-policy.spec', this commit:
140,610,489 PROGRAM TOTALS
58,348,925 rpmio/argv.c:argvCount
14,378,832 build/parseSpec.c:readLine
3,893,942 glibc-2.16-75f0d304/malloc/malloc.c:_int_malloc
3,490,055 rpm-4.10.2/lib/header.c:copyData
...
---
rpmio/macro.c | 94 ++++++++++++++++++++++++++++++++++++++---------------------
1 file changed, 61 insertions(+), 33 deletions(-)
diff --git a/rpmio/macro.c b/rpmio/macro.c
index 0b1aacb..eee7716 100644
--- a/rpmio/macro.c
+++ b/rpmio/macro.c
@@ -369,12 +369,16 @@ expandThis(MacroBuf mb, const char * src, size_t slen, char **target)
return rc;
}
+static void mbGrow(MacroBuf mb, size_t n)
+{
+ mb->buf = xrealloc(mb->buf, mb->tpos + MACROBUFSIZ + n + 1);
+ mb->nb += MACROBUFSIZ + n;
+}
+
static void mbAppend(MacroBuf mb, char c)
{
- if (mb->nb < 1) {
- mb->buf = xrealloc(mb->buf, mb->tpos + MACROBUFSIZ + 1);
- mb->nb += MACROBUFSIZ;
- }
+ if (mb->nb < 1)
+ mbGrow(mb, 1);
mb->buf[mb->tpos++] = c;
mb->buf[mb->tpos] = '\0';
mb->nb--;
@@ -383,14 +387,23 @@ static void mbAppend(MacroBuf mb, char c)
static void mbAppendStr(MacroBuf mb, const char *str)
{
size_t len = strlen(str);
- if (len > mb->nb) {
- mb->buf = xrealloc(mb->buf, mb->tpos + mb->nb + MACROBUFSIZ + len + 1);
- mb->nb += MACROBUFSIZ + len;
- }
- memcpy(mb->buf+mb->tpos, str, len + 1);
+ if (mb->nb < len)
+ mbGrow(mb, len);
+ memcpy(mb->buf + mb->tpos, str, len + 1);
mb->tpos += len;
mb->nb -= len;
}
+
+static void mbAppendMem(MacroBuf mb, const char *str, size_t len)
+{
+ if (mb->nb < len)
+ mbGrow(mb, len);
+ memcpy(mb->buf + mb->tpos, str, len);
+ mb->tpos += len;
+ mb->buf[mb->tpos] = '\0';
+ mb->nb -= len;
+}
+
/**
* Expand output of shell command into target buffer.
* @param mb macro expansion state
@@ -990,18 +1003,19 @@ expandMacro(MacroBuf mb, const char *src, size_t slen)
char *source = NULL;
/* Handle non-terminated substrings by creating a terminated copy */
- if (!slen)
- slen = strlen(src);
- source = xmalloc(slen + 1);
- strncpy(source, src, slen);
- source[slen] = '\0';
- s = source;
+ if (slen) {
+ source = xmalloc(slen + 1);
+ memcpy(source, src, slen);
+ source[slen] = '\0';
+ s = source;
+ }
if (mb->buf == NULL) {
- size_t blen = MACROBUFSIZ + strlen(s);
- mb->buf = xcalloc(blen + 1, sizeof(*mb->buf));
- mb->tpos = 0;
+ size_t blen = MACROBUFSIZ + slen ? slen : strlen(s);
+ mb->buf = xmalloc(blen + 1);
+ mb->buf[0] = '\0';
mb->nb = blen;
+ mb->tpos = 0;
}
tpos = mb->tpos; /* save expansion pointer for printExpand */
@@ -1014,23 +1028,38 @@ expandMacro(MacroBuf mb, const char *src, size_t slen)
return 1;
}
- while (rc == 0 && (c = *s) != '\0') {
- s++;
- /* Copy text until next macro */
- switch(c) {
- case '%':
- if (*s) { /* Ensure not end-of-string. */
- if (*s != '%')
- break;
- s++; /* skip first % in %% */
- }
- default:
- mbAppend(mb, c);
- continue;
+ while (rc == 0 && *s != '\0') {
+ /* Scan for % */
+ se = strchr(s, '%');
+ /* End of input */
+ if (se == NULL) {
+ mbAppendStr(mb, s);
+ break;
+ }
+ /* Copy text and expand %% to % */
+ if (se[1] == '%') {
+ size_t len = se - s + 1;
+ mbAppendMem(mb, s, len);
+ s += len + 1;
+ continue;
+ }
+ /* Copy text and handle the macro */
+ else {
+ size_t len = se - s;
+ switch (len) {
+ case 0: /* optimize for e.g. %{buildroot}%{_libdir} */
+ break;
+ case 1: /* optimize for e.g. %{name}-%{version} */
+ mbAppend(mb, *s);
break;
+ default:
+ mbAppendMem(mb, s, len);
+ break;
+ }
+ s += len + 1;
}
- /* Expand next macro */
+ /* Expand the macro */
f = fe = NULL;
g = ge = NULL;
if (mb->depth > 1) /* XXX full expansion for outermost level */
@@ -1282,7 +1311,6 @@ expandMacro(MacroBuf mb, const char *src, size_t slen)
s = se;
}
- mb->buf[mb->tpos] = '\0';
mb->depth--;
if (rc != 0 || mb->expand_trace)
printExpansion(mb, mb->buf+tpos, mb->buf+mb->tpos);
--
1.8.1
More information about the Rpm-maint
mailing list