From: Volker Lendecke Date: Wed, 22 Jul 2015 09:19:08 +0000 (+0200) Subject: tdb: Don't malloc for every record in traverse X-Git-Tag: tdb-1.3.10~398 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=91a17e54136c1ad143d8b740ea7c7592cd8a6a8d;p=thirdparty%2Fsamba.git tdb: Don't malloc for every record in traverse This gains a few percent in tdbbackup Signed-off-by: Volker Lendecke Reviewed-by: Michael Adam Autobuild-User(master): Volker Lendecke Autobuild-Date(master): Fri Jul 15 00:52:00 CEST 2016 on sn-devel-144 --- diff --git a/lib/tdb/common/traverse.c b/lib/tdb/common/traverse.c index e18e3c34fd3..f33ef34ab8d 100644 --- a/lib/tdb/common/traverse.c +++ b/lib/tdb/common/traverse.c @@ -148,6 +148,13 @@ static int tdb_traverse_internal(struct tdb_context *tdb, struct tdb_record rec; int ret = 0, count = 0; tdb_off_t off; + size_t recbuf_len; + + recbuf_len = 4096; + key.dptr = malloc(recbuf_len); + if (key.dptr == NULL) { + return -1; + } /* This was in the initialization, above, but the IRIX compiler * did not like it. crh @@ -159,15 +166,44 @@ static int tdb_traverse_internal(struct tdb_context *tdb, /* tdb_next_lock places locks on the record returned, and its chain */ while ((off = tdb_next_lock(tdb, tl, &rec)) != 0) { + tdb_len_t full_len = rec.key_len + rec.data_len; + int nread; + + if (full_len > recbuf_len) { + recbuf_len = full_len; + + /* + * No realloc, we don't need the old data and thus can + * do without the memcpy + */ + free(key.dptr); + key.dptr = malloc(recbuf_len); + + if (key.dptr == NULL) { + ret = -1; + if (tdb_unlock(tdb, tl->hash, tl->lock_rw) + != 0) { + goto out; + } + if (tdb_unlock_record(tdb, tl->off) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, + "tdb_traverse: malloc " + "failed and unlock_record " + "failed!\n")); + } + goto out; + } + } + if (off == TDB_NEXT_LOCK_ERR) { ret = -1; goto out; } count++; /* now read the full record */ - key.dptr = tdb_alloc_read(tdb, tl->off + sizeof(rec), - rec.key_len + rec.data_len); - if (!key.dptr) { + nread = tdb->methods->tdb_read(tdb, tl->off + sizeof(rec), + key.dptr, full_len, 0); + if (nread == -1) { ret = -1; if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) goto out; @@ -184,7 +220,6 @@ static int tdb_traverse_internal(struct tdb_context *tdb, /* Drop chain lock, call out */ if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) { ret = -1; - SAFE_FREE(key.dptr); goto out; } if (fn && fn(tdb, key, dbuf, private_data)) { @@ -194,13 +229,12 @@ static int tdb_traverse_internal(struct tdb_context *tdb, TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: unlock_record failed!\n"));; ret = -1; } - SAFE_FREE(key.dptr); goto out; } - SAFE_FREE(key.dptr); } tdb_trace(tdb, "tdb_traverse_end"); out: + SAFE_FREE(key.dptr); tdb->travlocks.next = tl->next; if (ret < 0) return -1;