From 34a78d935ac44fc73becc8bba213cdf0268bb5e0 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Mon, 20 Dec 2010 19:58:15 -0600 Subject: Remove need for memory allocation in _alpm_depcmp Noticed when tweaking testdb, when we run _alpm_depcmp in loops and call it seven million times, the strdup()/free() combo can add up. Remove the need for any string duplication by some pointer manipulation and use of strncmp instead of strcmp. Also kill the function logger and add an escape so we don't needlessly retrieve the list of provides. Signed-off-by: Dan McGee --- lib/libalpm/deps.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index 21578293..e37eb02e 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -322,9 +322,6 @@ static int dep_vercmp(const char *version1, pmdepmod_t mod, int _alpm_depcmp(pmpkg_t *pkg, pmdepend_t *dep) { alpm_list_t *i; - - ALPM_LOG_FUNC; - const char *pkgname = alpm_pkg_get_name(pkg); const char *pkgversion = alpm_pkg_get_version(pkg); int satisfy = 0; @@ -332,22 +329,29 @@ int _alpm_depcmp(pmpkg_t *pkg, pmdepend_t *dep) /* check (pkg->name, pkg->version) */ satisfy = (strcmp(pkgname, dep->name) == 0 && dep_vercmp(pkgversion, dep->mod, dep->version)); + if(satisfy) { + return(satisfy); + } /* check provisions, format : "name=version" */ for(i = alpm_pkg_get_provides(pkg); i && !satisfy; i = i->next) { - char *provname = strdup(i->data); - char *provver = strchr(provname, '='); + const char *provision = i->data; + const char *provver = strchr(provision, '='); if(provver == NULL) { /* no provision version */ satisfy = (dep->mod == PM_DEP_MOD_ANY - && strcmp(provname, dep->name) == 0); + && strcmp(provision, dep->name) == 0); } else { - *provver = '\0'; + /* This is a bit tricker than the old code for performance reasons. To + * prevent the need to copy and duplicate strings, strncmp only the name + * portion if they are the same length, since there is a version and + * operator in play here. */ + size_t namelen = provver - provision; provver += 1; - satisfy = (strcmp(provname, dep->name) == 0 + satisfy = (strlen(dep->name) == namelen + && strncmp(provision, dep->name, namelen) == 0 && dep_vercmp(provver, dep->mod, dep->version)); } - free(provname); } return(satisfy); -- cgit v1.2.3 From 735a197fc29b6b85a64cae5a6fa95e1209552c3b Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Tue, 21 Dec 2010 15:40:04 -0600 Subject: Use name hashes in depends to avoid strcmp calls Just like we did for package name comparsions, if we add a depend name_hash field on depend struct initialization, we can use it instead of doing a string name comparison, saving us a lot of checks in the depcmp code. Signed-off-by: Dan McGee --- lib/libalpm/deps.c | 23 ++++++++++++++++------- lib/libalpm/deps.h | 3 ++- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index e37eb02e..2ed9d30a 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -322,15 +322,20 @@ static int dep_vercmp(const char *version1, pmdepmod_t mod, int _alpm_depcmp(pmpkg_t *pkg, pmdepend_t *dep) { alpm_list_t *i; - const char *pkgname = alpm_pkg_get_name(pkg); - const char *pkgversion = alpm_pkg_get_version(pkg); + const char *pkgname = pkg->name; + const char *pkgversion = pkg->version; int satisfy = 0; /* check (pkg->name, pkg->version) */ - satisfy = (strcmp(pkgname, dep->name) == 0 - && dep_vercmp(pkgversion, dep->mod, dep->version)); - if(satisfy) { - return(satisfy); + if(pkg->name_hash && dep->name_hash + && pkg->name_hash != dep->name_hash) { + /* skip more expensive checks */ + } else { + satisfy = (strcmp(pkgname, dep->name) == 0 + && dep_vercmp(pkgversion, dep->mod, dep->version)); + if(satisfy) { + return(satisfy); + } } /* check provisions, format : "name=version" */ @@ -380,7 +385,8 @@ pmdepend_t *_alpm_splitdep(const char *depstring) depend->mod = PM_DEP_MOD_LE; *ptr = '\0'; ptr += 2; - } else if((ptr = strstr(newstr, "="))) { /* Note: we must do =,<,> checks after <=, >= checks */ + } else if((ptr = strstr(newstr, "="))) { + /* Note: we must do =,<,> checks after <=, >= checks */ depend->mod = PM_DEP_MOD_EQ; *ptr = '\0'; ptr += 1; @@ -396,6 +402,7 @@ pmdepend_t *_alpm_splitdep(const char *depstring) /* no version specified - copy the name and return it */ depend->mod = PM_DEP_MOD_ANY; STRDUP(depend->name, newstr, RET_ERR(PM_ERR_MEMORY, NULL)); + depend->name_hash = _alpm_hash_sdbm(depend->name); depend->version = NULL; free(newstr); return(depend); @@ -404,6 +411,7 @@ pmdepend_t *_alpm_splitdep(const char *depstring) /* if we get here, we have a version comparator, copy the right parts * to the right places */ STRDUP(depend->name, newstr, RET_ERR(PM_ERR_MEMORY, NULL)); + depend->name_hash = _alpm_hash_sdbm(depend->name); STRDUP(depend->version, ptr, RET_ERR(PM_ERR_MEMORY, NULL)); free(newstr); @@ -416,6 +424,7 @@ pmdepend_t *_alpm_dep_dup(const pmdepend_t *dep) CALLOC(newdep, 1, sizeof(pmdepend_t), RET_ERR(PM_ERR_MEMORY, NULL)); STRDUP(newdep->name, dep->name, RET_ERR(PM_ERR_MEMORY, NULL)); + newdep->name_hash = dep->name_hash; STRDUP(newdep->version, dep->version, RET_ERR(PM_ERR_MEMORY, NULL)); newdep->mod = dep->mod; diff --git a/lib/libalpm/deps.h b/lib/libalpm/deps.h index 6fa763e1..b720b364 100644 --- a/lib/libalpm/deps.h +++ b/lib/libalpm/deps.h @@ -29,9 +29,10 @@ /* Dependency */ struct __pmdepend_t { - pmdepmod_t mod; char *name; char *version; + long name_hash; + pmdepmod_t mod; }; /* Missing dependency */ -- cgit v1.2.3