summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@wiredtiger.com>2012-10-16 17:49:50 +1100
committerMichael Cahill <michael.cahill@wiredtiger.com>2012-10-16 17:49:50 +1100
commit044686f600158677da231fefac838d1fae857d93 (patch)
tree53a807890e39b363eec3e08fc8612664ebc49fd1
parent44c514d20d27ffb6cc6770fe41e65267de63b17d (diff)
downloadmongo-044686f600158677da231fefac838d1fae857d93.tar.gz
Tweak the search loops in hazard_{set,clear} in favor of last-in-first-out ordering.
-rw-r--r--src/include/api.h5
-rw-r--r--src/support/hazard.c24
2 files changed, 23 insertions, 6 deletions
diff --git a/src/include/api.h b/src/include/api.h
index f5aa7bd9050..4dd3fa9392d 100644
--- a/src/include/api.h
+++ b/src/include/api.h
@@ -127,8 +127,9 @@ struct __wt_session_impl {
* easily call a function to clear memory up to, but not including, the
* hazard reference.
*/
- uint32_t hazard_size; /* Count of used hazard references */
- u_int nhazard;
+ uint32_t hazard_size; /* Allocated slots in hazard array. */
+ uint32_t nhazard; /* Count of active hazard references */
+
#define WT_SESSION_CLEAR(s) memset(s, 0, WT_PTRDIFF(&(s)->hazard, s))
WT_HAZARD *hazard; /* Hazard reference array */
};
diff --git a/src/support/hazard.c b/src/support/hazard.c
index df362278d25..78dc1b5a1d8 100644
--- a/src/support/hazard.c
+++ b/src/support/hazard.c
@@ -24,6 +24,7 @@ __wt_hazard_set(WT_SESSION_IMPL *session, WT_REF *ref, int *busyp
{
WT_BTREE *btree;
WT_HAZARD *hp;
+ int restarts = 0;
btree = session->btree;
*busyp = 0;
@@ -45,12 +46,23 @@ __wt_hazard_set(WT_SESSION_IMPL *session, WT_REF *ref, int *busyp
* reference before it discards the page (the eviction server sets the
* state to WT_REF_LOCKED, then flushes memory and checks the hazard
* references).
+ *
+ * For sessions with many active hazard references, skip most of the
+ * active slots: there may be a free slot in there, but checking is
+ * expensive. Most hazard references are released quickly: optimize
+ * for that case.
*/
- for (hp = session->hazard; ; ++hp) {
+ for (hp = session->hazard + session->nhazard;; ++hp) {
/* Expand the number of hazard references if available.*/
if (hp >= session->hazard + session->hazard_size) {
if (session->hazard_size >= S2C(session)->hazard_max)
break;
+ /* Restart the search. */
+ if (session->nhazard < session->hazard_size &&
+ restarts++ == 0) {
+ hp = session->hazard;
+ continue;
+ }
WT_PUBLISH(session->hazard_size,
WT_MIN(session->hazard_size + WT_HAZARD_INCR,
S2C(session)->hazard_max));
@@ -134,9 +146,13 @@ __wt_hazard_clear(WT_SESSION_IMPL *session, WT_PAGE *page)
*/
WT_ASSERT(session, page != NULL);
- /* Clear the caller's hazard pointer. */
- for (hp = session->hazard;
- hp < session->hazard + session->hazard_size; ++hp)
+ /*
+ * Clear the caller's hazard pointer.
+ * The common pattern is LIFO, so do a reverse search.
+ */
+ for (hp = session->hazard + session->hazard_size - 1;
+ hp >= session->hazard;
+ --hp)
if (hp->page == page) {
/*
* We don't publish the hazard reference clear in the