]> git.sur5r.net Git - openldap/commitdiff
Keep re-using dpages instead of freeing them
authorHoward Chu <hyc@symas.com>
Fri, 19 Aug 2011 23:43:57 +0000 (16:43 -0700)
committerHoward Chu <hyc@symas.com>
Thu, 1 Sep 2011 23:31:10 +0000 (16:31 -0700)
libraries/libmdb/mdb.c

index c6ce7a7dd3fcef05fe272a2962d7fc1bfef6c390..d197facbf5ba231baed0508f7480e0d72e4c8545 100644 (file)
@@ -339,6 +339,7 @@ struct MDB_env {
        MDB_db          *me_dbs[2];
        MDB_oldpages *me_pghead;
        pthread_key_t   me_txkey;       /* thread-key for readers */
+       MDB_dpage       *me_dpages;
        pgno_t          me_free_pgs[MDB_IDL_UM_SIZE];
        MIDL2           me_dirty_list[MDB_IDL_DB_SIZE];
 };
@@ -610,8 +611,13 @@ mdb_alloc_page(MDB_txn *txn, MDB_page *parent, unsigned int parent_idx, int num)
                if (txn->mt_next_pgno + num >= txn->mt_env->me_maxpg)
                        return NULL;
        }
-       if ((dp = malloc(txn->mt_env->me_psize * num + sizeof(MDB_dhead))) == NULL)
-               return NULL;
+       if (txn->mt_env->me_dpages && num == 1) {
+               dp = txn->mt_env->me_dpages;
+               txn->mt_env->me_dpages = (MDB_dpage *)dp->h.md_parent;
+       } else {
+               if ((dp = malloc(txn->mt_env->me_psize * num + sizeof(MDB_dhead))) == NULL)
+                       return NULL;
+       }
        dp->h.md_num = num;
        dp->h.md_parent = parent;
        dp->h.md_pi = parent_idx;
@@ -771,11 +777,20 @@ mdb_txn_abort(MDB_txn *txn)
                txn->mt_u.reader->mr_txnid = 0;
        } else {
                MDB_oldpages *mop;
+               MDB_dpage *dp;
                unsigned int i;
 
-               /* Discard all dirty pages. */
-               for (i=1; i<=txn->mt_u.dirty_list[0].mid; i++)
-                       free(txn->mt_u.dirty_list[i].mptr);
+               /* return all dirty pages to dpage list */
+               for (i=1; i<=txn->mt_u.dirty_list[0].mid; i++) {
+                       dp = txn->mt_u.dirty_list[i].mptr;
+                       if (dp->h.md_num == 1) {
+                               dp->h.md_parent = (MDB_page *)txn->mt_env->me_dpages;
+                               txn->mt_env->me_dpages = dp;
+                       } else {
+                               /* large pages just get freed directly */
+                               free(dp);
+                       }
+               }
 
                while ((mop = txn->mt_env->me_pghead)) {
                        txn->mt_env->me_pghead = mop->mo_next;
@@ -953,8 +968,16 @@ mdb_txn_commit(MDB_txn *txn)
 
        /* Drop the dirty pages.
         */
-       for (i=1; i<=txn->mt_u.dirty_list[0].mid; i++)
-               free(txn->mt_u.dirty_list[i].mptr);
+       for (i=1; i<=txn->mt_u.dirty_list[0].mid; i++) {
+               dp = txn->mt_u.dirty_list[i].mptr;
+               if (dp->h.md_num == 1) {
+                       dp->h.md_parent = (MDB_page *)txn->mt_env->me_dpages;
+                       txn->mt_env->me_dpages = dp;
+               } else {
+                       free(dp);
+               }
+               txn->mt_u.dirty_list[i].mid = 0;
+       }
 
        if ((n = mdb_env_sync(env, 0)) != 0 ||
            (n = mdb_env_write_meta(txn)) != MDB_SUCCESS) {
@@ -1450,9 +1473,17 @@ leave:
 void
 mdb_env_close(MDB_env *env)
 {
+       MDB_dpage *dp;
+
        if (env == NULL)
                return;
 
+       while (env->me_dpages) {
+               dp = env->me_dpages;
+               env->me_dpages = (MDB_dpage *)dp->h.md_parent;
+               free(dp);
+       }
+
        free(env->me_dbs[1]);
        free(env->me_dbs[0]);
        free(env->me_dbxs);