From c6a4982793ba5d0818b3e9b85dff0304dcaadf52 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Thu, 14 Feb 2013 19:20:45 +0000 Subject: [PATCH] More for ITS#7455 Don't memmove freelist entry when chunking it. Just advance the pointer, now that it's no longer a complex struct. Also just calculate maxfree_1pg at startup; it's a constant during runtime. --- libraries/liblmdb/mdb.c | 44 +++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index e1f6357c7f..7bfdfc27bc 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -941,12 +941,15 @@ struct MDB_env { MDB_dbx *me_dbxs; /**< array of static DB info */ uint16_t *me_dbflags; /**< array of flags from MDB_db.md_flags */ pgno_t *me_pghead; /**< old pages reclaimed from freelist */ + pgno_t *me_pgfree; /**< memory to free when dropping me_pghead */ pthread_key_t me_txkey; /**< thread-key for readers */ MDB_page *me_dpages; /**< list of malloc'd blocks for re-use */ /** IDL of pages that became unused in a write txn */ MDB_IDL me_free_pgs; /** ID2L of pages that were written during a write txn */ MDB_ID2 me_dirty_list[MDB_IDL_UM_SIZE]; + /** Max number of freelist items that can fit in a single overflow page */ + unsigned int me_maxfree_1pg; #ifdef _WIN32 HANDLE me_rmutex; /* Windows mutexes don't reside in shared mem */ HANDLE me_wmutex; @@ -1337,7 +1340,7 @@ again: if (!mop) return ENOMEM; txn->mt_env->me_pglast = last; - txn->mt_env->me_pghead = mop; + txn->mt_env->me_pghead = txn->mt_env->me_pgfree = mop; memcpy(mop, idl, MDB_IDL_SIZEOF(idl)); #if MDB_DEBUG > 1 @@ -1422,8 +1425,8 @@ none: mop2[k--] = mop[j--]; } txn->mt_env->me_pglast = last; - txn->mt_env->me_pghead = mop2; - free(mop); + free(txn->mt_env->me_pgfree); + txn->mt_env->me_pghead = txn->mt_env->me_pgfree = mop2; mop = mop2; /* Keep trying to read until we have enough */ if (mop[0] < (unsigned)num) { @@ -1457,8 +1460,8 @@ none: mop[0]--; } if (MDB_IDL_IS_ZERO(mop)) { - txn->mt_env->me_pghead = NULL; - free(mop); + free(txn->mt_env->me_pgfree); + txn->mt_env->me_pghead = txn->mt_env->me_pgfree = NULL; } } } @@ -1931,7 +1934,6 @@ mdb_txn_reset0(MDB_txn *txn) if (!(env->me_flags & MDB_ROFS)) txn->mt_u.reader->mr_txnid = (txnid_t)-1; } else { - pgno_t *mop; MDB_page *dp; unsigned int i; @@ -1971,10 +1973,8 @@ mdb_txn_reset0(MDB_txn *txn) env->me_free_pgs = txn->mt_free_pgs; } - if ((mop = txn->mt_env->me_pghead) != NULL) { - txn->mt_env->me_pghead = NULL; - free(mop); - } + free(txn->mt_env->me_pgfree); + txn->mt_env->me_pghead = txn->mt_env->me_pgfree = NULL; txn->mt_env->me_pglast = 0; env->me_txn = NULL; @@ -2022,7 +2022,7 @@ mdb_txn_commit(MDB_txn *txn) off_t size; MDB_page *dp; MDB_env *env; - pgno_t next, freecnt, maxfree_1pg; + pgno_t next, freecnt; txnid_t oldpg_txnid, id; MDB_cursor mc; @@ -2148,12 +2148,6 @@ mdb_txn_commit(MDB_txn *txn) mdb_cursor_init(&mc, txn, FREE_DBI, NULL); oldpg_txnid = id = 0; freecnt = 0; - /* Preferred max #items per freelist entry, to avoid overflow pages. - * Leave room for headers, key (txnid), pagecount (pageno_t), and - * FIXME: a bit more in case there is some delimiter I don't know about. - */ - maxfree_1pg = (env->me_psize - (PAGEHDRSZ + NODESIZE + 3*sizeof(MDB_ID))) - / sizeof(pgno_t); /* should only be one record now */ if (env->me_pghead || env->me_pglast) { @@ -2246,8 +2240,8 @@ free2: i = 2; do { orig = mop[0]; - if (orig > maxfree_1pg && id > 4) - orig = maxfree_1pg; /* Do not use an overflow page */ + if (orig > env->me_maxfree_1pg && id > 4) + orig = env->me_maxfree_1pg; /* Do not use more than 1 page */ data.mv_size = (orig + 1) * sizeof(pgno_t); rc = mdb_cursor_put(&mc, &key, &data, MDB_RESERVE); if (rc) @@ -2262,9 +2256,8 @@ free2: if (mop[0] <= orig) break; *(pgno_t *)data.mv_data = orig; - mop[0] -= orig; - memmove(&mop[1], &mop[1 + orig], - mop[0] * sizeof(pgno_t)); + mop[orig] = mop[0] - orig; + env->me_pghead = mop += orig; /* Save more oldpages at the previous txnid. */ assert(env->me_pglast == id && id == oldpg_txnid); env->me_pglast = --oldpg_txnid; @@ -2275,10 +2268,8 @@ free2: if (freecnt != txn->mt_free_pgs[0]) goto free2; - if (env->me_pghead) { - free(env->me_pghead); - env->me_pghead = NULL; - } + free(env->me_pgfree); + env->me_pghead = env->me_pgfree = NULL; if (!MDB_IDL_IS_ZERO(txn->mt_free_pgs)) { if (mdb_midl_shrink(&txn->mt_free_pgs)) @@ -2842,6 +2833,7 @@ mdb_env_open2(MDB_env *env) return EBUSY; /* TODO: Make a new MDB_* error code? */ } env->me_psize = meta.mm_psize; + env->me_maxfree_1pg = (env->me_psize - PAGEHDRSZ) / sizeof(pgno_t) - 1; env->me_maxpg = env->me_mapsize / env->me_psize; -- 2.39.5