summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@wiredtiger.com>2013-03-13 13:08:48 +1100
committerMichael Cahill <michael.cahill@wiredtiger.com>2013-03-13 13:08:48 +1100
commit9b980cb70e04b766beaab510bcdee12ca0a375e4 (patch)
tree5e7cf16dc224ce38443beb2227aa815d5b2fe233
parentadb56742e2e9a88232c0dd215e8901a6a5ffc19a (diff)
downloadmongo-9b980cb70e04b766beaab510bcdee12ca0a375e4.tar.gz
Avoid polling global transaction state if nothing has changed.
-rw-r--r--src/btree/rec_track.c7
-rw-r--r--src/include/txn.h5
-rw-r--r--src/txn/txn.c54
3 files changed, 35 insertions, 31 deletions
diff --git a/src/btree/rec_track.c b/src/btree/rec_track.c
index 92e98212b65..c01c87e609e 100644
--- a/src/btree/rec_track.c
+++ b/src/btree/rec_track.c
@@ -67,7 +67,7 @@ static int
__rec_track_extend(WT_SESSION_IMPL *session, WT_PAGE *page)
{
WT_PAGE_MODIFY *mod;
- size_t bytes_allocated;
+ size_t bytes_allocated, newlen;
mod = page->modify;
@@ -81,9 +81,10 @@ __rec_track_extend(WT_SESSION_IMPL *session, WT_PAGE *page)
* page.
*/
bytes_allocated = mod->track_entries * sizeof(*mod->track);
+ newlen = WT_MAX(2 * mod->track_entries, mod->track_entries + 20);
WT_RET(__wt_realloc(session, &bytes_allocated,
- (mod->track_entries + 20) * sizeof(*mod->track), &mod->track));
- mod->track_entries += 20;
+ newlen * sizeof(*mod->track), &mod->track));
+ mod->track_entries = newlen;
return (0);
}
diff --git a/src/include/txn.h b/src/include/txn.h
index 813ecfb793e..75a33f6924a 100644
--- a/src/include/txn.h
+++ b/src/include/txn.h
@@ -49,6 +49,7 @@ struct __wt_txn_state {
struct __wt_txn_global {
volatile wt_txnid_t current; /* Current transaction ID. */
+ volatile uint32_t gen; /* Completed transaction genertion */
WT_TXN_STATE *states; /* Per-session transaction states */
};
@@ -79,6 +80,10 @@ struct __wt_txn {
*/
wt_txnid_t oldest_snap_min;
+ /* Saved global state, to avoid scans. */
+ wt_txnid_t last_id;
+ uint32_t last_gen, last_oldest_gen;
+
/*
* Arrays of txn IDs in WT_UPDATE or WT_REF structures created or
* modified by this transaction.
diff --git a/src/txn/txn.c b/src/txn/txn.c
index 7ee269525e3..fb7eeb6742a 100644
--- a/src/txn/txn.c
+++ b/src/txn/txn.c
@@ -79,6 +79,12 @@ __wt_txn_get_oldest(WT_SESSION_IMPL *session)
conn = S2C(session);
txn = &session->txn;
txn_global = &conn->txn_global;
+
+ /* If nothing has changed since last time, we're done. */
+ if (txn->last_oldest_gen == txn_global->gen)
+ return;
+ txn->last_oldest_gen = txn_global->gen;
+
oldest_snap_min =
(txn->id != WT_TXN_NONE) ? txn->id : txn_global->current;
@@ -114,9 +120,16 @@ __wt_txn_get_snapshot(
txn_global = &conn->txn_global;
txn_state = &txn_global->states[session->id];
+ /* If nothing has changed since last time, we're done. */
+ if (txn->last_id == txn_global->current &&
+ txn->last_gen == txn_global->gen)
+ return;
+
do {
/* Take a copy of the current session ID. */
- current_id = oldest_snap_min = txn_global->current;
+ txn->last_gen = txn->last_oldest_gen = txn_global->gen;
+ txn->last_id = oldest_snap_min = current_id =
+ txn_global->current;
/* Copy the array of concurrent transactions. */
WT_ORDERED_READ(session_cnt, conn->session_cnt);
@@ -153,39 +166,19 @@ __wt_txn_get_snapshot(
/*
* __wt_txn_get_evict_snapshot --
* Set up a snapshot in the current transaction for eviction.
- * No changes that are invisible to any active transaction can be evicted.
+ * Only changes that visible to all active transactions can be evicted.
*/
void
__wt_txn_get_evict_snapshot(WT_SESSION_IMPL *session)
{
- WT_CONNECTION_IMPL *conn;
- WT_TXN_GLOBAL *txn_global;
- WT_TXN_STATE *s;
- wt_txnid_t current_id, id, oldest_snap_min;
- uint32_t i, session_cnt;
-
- conn = S2C(session);
- txn_global = &conn->txn_global;
-
- do {
- /* Take a copy of the current session ID. */
- current_id = oldest_snap_min = txn_global->current;
+ WT_TXN *txn;
- /* Walk the array of concurrent transactions. */
- WT_ORDERED_READ(session_cnt, conn->session_cnt);
- for (i = 0, s = txn_global->states; i < session_cnt; i++, s++)
- if ((id = s->snap_min) != WT_TXN_NONE &&
- TXNID_LT(id, oldest_snap_min))
- oldest_snap_min = id;
+ txn = &session->txn;
- /*
- * Ensure the snapshot reads are scheduled before re-checking
- * the global current ID.
- */
- WT_READ_BARRIER();
- } while (current_id != txn_global->current);
+ __wt_txn_get_oldest(session);
+ __txn_sort_snapshot(
+ session, 0, txn->oldest_snap_min, txn->oldest_snap_min);
- __txn_sort_snapshot(session, 0, oldest_snap_min, oldest_snap_min);
/*
* Note that we carefully don't update the global table with this
* snap_min value: there is already a running transaction in this
@@ -249,7 +242,6 @@ __wt_txn_begin(WT_SESSION_IMPL *session, const char *cfg[])
txn->id = WT_ATOMIC_ADD(txn_global->current, 1);
} while (txn->id == WT_TXN_NONE || txn->id == WT_TXN_ABORTED);
WT_PUBLISH(txn_state->id, txn->id);
- oldest_snap_min = txn->id;
/*
* If we are starting a snapshot isolation transaction, get
@@ -260,6 +252,9 @@ __wt_txn_begin(WT_SESSION_IMPL *session, const char *cfg[])
* visible.
*/
if (txn->isolation == TXN_ISO_SNAPSHOT) {
+ txn->last_gen = txn->last_oldest_gen = txn_global->gen;
+ oldest_snap_min = txn->id;
+
/* Copy the array of concurrent transactions. */
WT_ORDERED_READ(session_cnt, conn->session_cnt);
for (i = n = 0, s = txn_global->states;
@@ -319,6 +314,9 @@ __wt_txn_release(WT_SESSION_IMPL *session)
__wt_txn_release_snapshot(session);
txn->isolation = session->isolation;
F_CLR(txn, TXN_ERROR | TXN_OLDEST | TXN_RUNNING);
+
+ /* Update the global generation number. */
+ ++S2C(session)->txn_global.gen;
}
/*