From 604a54277ed21f1fd983c205ad7d36feb3950ce1 Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Sat, 29 Nov 2008 13:52:32 +0200 Subject: [PATCH] Unify dbiIndexSet allocations, allocate in power-of-two sizes - allocating in even sized chunks helps avoiding crazy memory fragmentation when resizing a lot (rhbz#472507) - HEAD doesn't really need, rpm 4.6.x does, but doesn't hurt either... --- lib/rpmdb.c | 33 +++++++++++++++++++++++---------- lib/rpmdb_internal.h | 1 + 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/lib/rpmdb.c b/lib/rpmdb.c index 6659f8d..bc5c9ed 100644 --- a/lib/rpmdb.c +++ b/lib/rpmdb.c @@ -334,6 +334,25 @@ union _dbswap { \ } +/* + * Ensure sufficient memory for nrecs of new records in dbiIndexSet. + * Allocate in power of two sizes to avoid memory fragmentation, so + * realloc is not always needed. + */ +static inline void dbiGrowSet(dbiIndexSet set, unsigned int nrecs) +{ + size_t need = (set->count + nrecs) * sizeof(*(set->recs)); + size_t alloced = set->alloced ? set->alloced : 1 << 4; + + while (alloced < need) + alloced <<= 1; + + if (alloced != set->alloced) { + set->recs = xrealloc(set->recs, alloced); + set->alloced = alloced; + } +} + /** * Convert retrieved data to index set. * @param dbi index database handle @@ -356,9 +375,9 @@ static int dbt2set(dbiIndex dbi, DBT * data, dbiIndexSet * setp) return 0; } - set = xmalloc(sizeof(*set)); + set = xcalloc(1, sizeof(*set)); + dbiGrowSet(set, data->size / dbi->dbi_jlen); set->count = data->size / dbi->dbi_jlen; - set->recs = xmalloc(set->count * sizeof(*(set->recs))); switch (dbi->dbi_jlen) { default: @@ -483,9 +502,7 @@ static int dbiAppendSet(dbiIndexSet set, const void * recs, if (set == NULL || recs == NULL || nrecs <= 0 || recsize == 0) return 1; - set->recs = xrealloc(set->recs, - (set->count + nrecs) * sizeof(*(set->recs))); - + dbiGrowSet(set, nrecs); memset(set->recs + set->count, 0, nrecs * sizeof(*(set->recs))); while (nrecs-- > 0) { @@ -2165,11 +2182,7 @@ static int rpmdbGrowIterator(rpmdbMatchIterator mi) if (mi->mi_set == NULL) { mi->mi_set = set; } else { -#if 0 -fprintf(stderr, "+++ %d = %d + %d\t\"%s\"\n", (mi->mi_set->count + set->count), mi->mi_set->count, set->count, ((char *)key->data)); -#endif - mi->mi_set->recs = xrealloc(mi->mi_set->recs, - (mi->mi_set->count + set->count) * sizeof(*(mi->mi_set->recs))); + dbiGrowSet(mi->mi_set, set->count); memcpy(mi->mi_set->recs + mi->mi_set->count, set->recs, set->count * sizeof(*(mi->mi_set->recs))); mi->mi_set->count += set->count; diff --git a/lib/rpmdb_internal.h b/lib/rpmdb_internal.h index d19733c..79a81ad 100644 --- a/lib/rpmdb_internal.h +++ b/lib/rpmdb_internal.h @@ -38,6 +38,7 @@ struct _dbiIndexItem { struct _dbiIndexSet { struct _dbiIndexItem * recs; /*!< array of records */ unsigned int count; /*!< number of records */ + size_t alloced; /*!< alloced size */ }; /** \ingroup dbi -- 2.7.4