summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@mongodb.com>2016-08-26 12:50:11 +1000
committerAlex Gorrod <alexander.gorrod@mongodb.com>2016-08-26 12:50:11 +1000
commita48b73bdd3da302262582a04830e981ca60ad1cb (patch)
tree09035bcdfaf9edeba769ffe6b4fc9270daa2bbca
parent0cdefa89f437bab5aaf554a2fa211028b674bbd0 (diff)
downloadmongo-a48b73bdd3da302262582a04830e981ca60ad1cb.tar.gz
WT-2816 General improvements to WiredTiger eviction performance (#2949)
A set of changes to the eviction algorithm including: * Fix a bug in how many items can be added to the urgent queue * Have the eviction server sleep less so it recovers from disruptions faster. * Only have application threads evict dirty pages if they are blocked on the dirty trigger. * Swap eviction queues when one becomes empty. * Have the eviction server populate the "other" queue whenever it notices that it isn't full.
-rw-r--r--bench/wtperf/wtperf.c3
-rw-r--r--dist/stat_data.py6
-rw-r--r--src/conn/conn_cache.c8
-rw-r--r--src/conn/conn_dhandle.c4
-rw-r--r--src/evict/evict_lru.c334
-rw-r--r--src/evict/evict_page.c6
-rw-r--r--src/include/btree.i2
-rw-r--r--src/include/cache.h29
-rw-r--r--src/include/cache.i38
-rw-r--r--src/include/extern.h2
-rw-r--r--src/include/stat.h2
-rw-r--r--src/include/wiredtiger.in10
-rw-r--r--src/support/stat.c11
-rw-r--r--src/txn/txn_ckpt.c2
-rw-r--r--test/csuite/wt2834_join_bloom_fix/main.c7
-rw-r--r--tools/wtstats/stat_data.py6
16 files changed, 290 insertions, 180 deletions
diff --git a/bench/wtperf/wtperf.c b/bench/wtperf/wtperf.c
index d969d625b76..d3d54fff6e3 100644
--- a/bench/wtperf/wtperf.c
+++ b/bench/wtperf/wtperf.c
@@ -1540,8 +1540,7 @@ execute_populate(CONFIG *cfg)
print_ops_sec = 0;
} else {
print_secs = (double)msecs / (double)MSEC_PER_SEC;
- print_ops_sec =
- (uint64_t)((cfg->icount / msecs) / MSEC_PER_SEC);
+ print_ops_sec = (uint64_t)(cfg->icount / print_secs);
}
lprintf(cfg, 0, 1,
"Load time: %.2f\n" "load ops/sec: %" PRIu64,
diff --git a/dist/stat_data.py b/dist/stat_data.py
index 51cc487f04c..af410a341bd 100644
--- a/dist/stat_data.py
+++ b/dist/stat_data.py
@@ -201,12 +201,12 @@ connection_stats = [
CacheStat('cache_eviction_queue_empty', 'eviction server candidate queue empty when topping up'),
CacheStat('cache_eviction_queue_not_empty', 'eviction server candidate queue not empty when topping up'),
CacheStat('cache_eviction_server_evicting', 'eviction server evicting pages'),
- CacheStat('cache_eviction_server_not_evicting', 'eviction server populating queue, but not evicting pages'),
CacheStat('cache_eviction_server_slept', 'eviction server slept, because we did not make progress with eviction'),
CacheStat('cache_eviction_server_toobig', 'eviction server skipped very large page'),
CacheStat('cache_eviction_slow', 'eviction server unable to reach eviction goal'),
CacheStat('cache_eviction_split_internal', 'internal pages split during eviction'),
CacheStat('cache_eviction_split_leaf', 'leaf pages split during eviction'),
+ CacheStat('cache_eviction_state', 'eviction state', 'no_clear,no_scale'),
CacheStat('cache_eviction_walk', 'pages walked for eviction'),
CacheStat('cache_eviction_walks_active', 'files with active eviction walks', 'no_clear,no_scale,size'),
CacheStat('cache_eviction_walks_started', 'files with new eviction walks started'),
@@ -276,8 +276,8 @@ connection_stats = [
LogStat('log_slot_unbuffered', 'consolidated slot unbuffered writes'),
LogStat('log_sync', 'log sync operations'),
LogStat('log_sync_dir', 'log sync_dir operations'),
- LogStat('log_sync_dir_duration', 'log sync_dir time duration (usecs)'),
- LogStat('log_sync_duration', 'log sync time duration (usecs)'),
+ LogStat('log_sync_dir_duration', 'log sync_dir time duration (usecs)', 'no_clear,no_scale'),
+ LogStat('log_sync_duration', 'log sync time duration (usecs)', 'no_clear,no_scale'),
LogStat('log_write_lsn', 'log server thread advances write LSN'),
LogStat('log_write_lsn_skip', 'log server thread write LSN walk skipped'),
LogStat('log_writes', 'log write operations'),
diff --git a/src/conn/conn_cache.c b/src/conn/conn_cache.c
index e5de28887de..ba1e0210334 100644
--- a/src/conn/conn_cache.c
+++ b/src/conn/conn_cache.c
@@ -179,9 +179,11 @@ __wt_cache_create(WT_SESSION_IMPL *session, const char *cfg[])
&cache->evict_queues[i].evict_lock, "cache eviction"));
}
- /* Ensure there is always a non-NULL current queue. */
- cache->evict_current_queue =
- &cache->evict_queues[WT_EVICT_URGENT_QUEUE + 1];
+ /* Ensure there are always non-NULL queues. */
+ cache->evict_current_queue = cache->evict_fill_queue =
+ &cache->evict_queues[0];
+ cache->evict_other_queue = &cache->evict_queues[1];
+ cache->evict_urgent_queue = &cache->evict_queues[WT_EVICT_URGENT_QUEUE];
/*
* We get/set some values in the cache statistics (rather than have
diff --git a/src/conn/conn_dhandle.c b/src/conn/conn_dhandle.c
index 3f242b9df7e..9eb4d4a7746 100644
--- a/src/conn/conn_dhandle.c
+++ b/src/conn/conn_dhandle.c
@@ -572,14 +572,14 @@ __wt_conn_dhandle_discard_single(
set_pass_intr = false;
if (!F_ISSET(session, WT_SESSION_LOCKED_HANDLE_LIST)) {
set_pass_intr = true;
- (void)__wt_atomic_add32(&S2C(session)->cache->pass_intr, 1);
+ (void)__wt_atomic_addv32(&S2C(session)->cache->pass_intr, 1);
}
/* Try to remove the handle, protected by the data handle lock. */
WT_WITH_HANDLE_LIST_LOCK(session,
tret = __conn_dhandle_remove(session, final));
if (set_pass_intr)
- (void)__wt_atomic_sub32(&S2C(session)->cache->pass_intr, 1);
+ (void)__wt_atomic_subv32(&S2C(session)->cache->pass_intr, 1);
WT_TRET(tret);
/*
diff --git a/src/evict/evict_lru.c b/src/evict/evict_lru.c
index 8700f06b4a2..56fba412c56 100644
--- a/src/evict/evict_lru.c
+++ b/src/evict/evict_lru.c
@@ -9,15 +9,15 @@
#include "wt_internal.h"
static int __evict_clear_all_walks(WT_SESSION_IMPL *);
-static int __evict_helper(WT_SESSION_IMPL *);
static int WT_CDECL __evict_lru_cmp(const void *, const void *);
static int __evict_lru_pages(WT_SESSION_IMPL *, bool);
static int __evict_lru_walk(WT_SESSION_IMPL *);
static int __evict_page(WT_SESSION_IMPL *, bool);
static int __evict_pass(WT_SESSION_IMPL *);
static int __evict_server(WT_SESSION_IMPL *, bool *);
-static int __evict_walk(WT_SESSION_IMPL *, uint32_t);
-static int __evict_walk_file(WT_SESSION_IMPL *, uint32_t, u_int, u_int *);
+static int __evict_walk(WT_SESSION_IMPL *, WT_EVICT_QUEUE *);
+static int __evict_walk_file(
+ WT_SESSION_IMPL *, WT_EVICT_QUEUE *, u_int, u_int *, bool *);
#define WT_EVICT_HAS_WORKERS(s) \
(S2C(s)->evict_threads.current_threads > 1)
@@ -52,6 +52,10 @@ __evict_read_gen(const WT_EVICT_ENTRY *entry)
if (__wt_page_is_empty(page))
return (WT_READGEN_OLDEST);
+ /* Any large page in memory is likewise a good choice. */
+ if (page->memory_footprint > btree->splitmempage)
+ return (WT_READGEN_OLDEST);
+
/*
* The base read-generation is skewed by the eviction priority.
* Internal pages are also adjusted, we prefer to evict leaf pages.
@@ -139,6 +143,29 @@ __wt_evict_list_clear_page(WT_SESSION_IMPL *session, WT_REF *ref)
}
/*
+ * __evict_queue_empty --
+ * Is the queue empty?
+ */
+static inline bool
+__evict_queue_empty(WT_EVICT_QUEUE *queue)
+{
+ return (queue->evict_current == NULL ||
+ queue->evict_candidates == 0);
+}
+
+/*
+ * __evict_queue_full --
+ * Is the queue full (i.e., it has been populated with candidates and none
+ * of them have been evicted yet)?
+ */
+static inline bool
+__evict_queue_full(WT_EVICT_QUEUE *queue)
+{
+ return (queue->evict_current == queue->evict_queue &&
+ queue->evict_candidates != 0);
+}
+
+/*
* __wt_evict_server_wake --
* Wake the eviction server thread.
*/
@@ -216,7 +243,7 @@ __wt_evict_thread_run(WT_SESSION_IMPL *session, WT_THREAD *thread)
session, cache->evict_cond, did_work);
__wt_verbose(session, WT_VERB_EVICTSERVER, "waking");
} else
- WT_ERR(__evict_helper(session));
+ WT_ERR(__evict_lru_pages(session, false));
}
/*
@@ -390,25 +417,6 @@ __wt_evict_destroy(WT_SESSION_IMPL *session)
}
/*
- * __evict_helper --
- * Thread to help evict pages from the cache.
- */
-static int
-__evict_helper(WT_SESSION_IMPL *session)
-{
- WT_CONNECTION_IMPL *conn;
- WT_DECL_RET;
-
- conn = S2C(session);
-
- if ((ret = __evict_lru_pages(session, false)) == WT_NOTFOUND)
- __wt_cond_wait(session, conn->evict_threads.wait_cond, 10000);
- else
- WT_RET(ret);
- return (0);
-}
-
-/*
* __evict_update_work --
* Configure eviction work state.
*/
@@ -429,16 +437,7 @@ __evict_update_work(WT_SESSION_IMPL *session)
if (!F_ISSET(conn, WT_CONN_EVICTION_RUN))
return (false);
- /*
- * Setup the number of refs to consider in each handle, depending
- * on how many handles are open. We want to consider less candidates
- * from each file as more files are open. Handle the case where there
- * are no files open by adding 1.
- */
- cache->evict_max_refs_per_file =
- WT_MAX(100, WT_MILLION / (conn->open_file_count + 1));
-
- if (cache->evict_queues[WT_EVICT_URGENT_QUEUE].evict_current != NULL)
+ if (!__evict_queue_empty(cache->evict_urgent_queue))
FLD_SET(cache->state, WT_EVICT_STATE_URGENT);
/*
@@ -451,19 +450,25 @@ __evict_update_work(WT_SESSION_IMPL *session)
bytes_inuse = __wt_cache_bytes_inuse(cache);
if (bytes_inuse > (cache->eviction_target * bytes_max) / 100)
FLD_SET(cache->state, WT_EVICT_STATE_CLEAN);
+ if (bytes_inuse > (cache->eviction_trigger * bytes_max) / 100)
+ FLD_SET(cache->state, WT_EVICT_STATE_CLEAN_HARD);
+
+ dirty_inuse = __wt_cache_dirty_leaf_inuse(cache);
+ if (dirty_inuse > (cache->eviction_dirty_target * bytes_max) / 100)
+ FLD_SET(cache->state, WT_EVICT_STATE_DIRTY);
+ if (dirty_inuse > (cache->eviction_dirty_trigger * bytes_max) / 100)
+ FLD_SET(cache->state, WT_EVICT_STATE_DIRTY_HARD);
/*
* Scrub dirty pages and keep them in cache if we are less than half
- * way between the cache target and trigger.
+ * way to the clean or dirty trigger.
*/
if (bytes_inuse < ((cache->eviction_target + cache->eviction_trigger) *
+ bytes_max) / 200 && dirty_inuse <
+ ((cache->eviction_dirty_target + cache->eviction_dirty_trigger) *
bytes_max) / 200)
FLD_SET(cache->state, WT_EVICT_STATE_SCRUB);
- dirty_inuse = __wt_cache_dirty_leaf_inuse(cache);
- if (dirty_inuse > (cache->eviction_dirty_target * bytes_max) / 100)
- FLD_SET(cache->state, WT_EVICT_STATE_DIRTY);
-
/*
* If the cache has been stuck and is now under control, clear the
* stuck flag.
@@ -479,6 +484,8 @@ __evict_update_work(WT_SESSION_IMPL *session)
FLD_SET(cache->state, WT_EVICT_STATE_AGGRESSIVE);
}
+ WT_STAT_FAST_CONN_SET(session, cache_eviction_state, cache->state);
+
return (FLD_ISSET(cache->state,
WT_EVICT_STATE_ALL | WT_EVICT_STATE_URGENT));
}
@@ -555,7 +562,17 @@ __evict_pass(WT_SESSION_IMPL *session)
cache->bytes_dirty_intl + cache->bytes_dirty_leaf);
WT_RET(__evict_lru_walk(session));
- WT_RET_NOTFOUND_OK(__evict_lru_pages(session, true));
+
+ /*
+ * If the queue has been empty recently, keep queuing more
+ * pages to evict. If the rate of queuing pages is high
+ * enough, this score will go to zero, in which case the
+ * eviction server might as well help out with eviction.
+ */
+ if (cache->evict_empty_score < WT_EVICT_EMPTY_SCORE_CUTOFF ||
+ (!WT_EVICT_HAS_WORKERS(session) &&
+ !__evict_queue_empty(cache->evict_urgent_queue)))
+ WT_RET_NOTFOUND_OK(__evict_lru_pages(session, true));
/*
* If we're making progress, keep going; if we're not making
@@ -575,8 +592,7 @@ __evict_pass(WT_SESSION_IMPL *session)
*/
WT_STAT_FAST_CONN_INCR(session,
cache_eviction_server_slept);
- __wt_cond_wait(session,
- cache->evict_cond, WT_THOUSAND * WT_MAX(loop, 1));
+ __wt_cond_wait(session, cache->evict_cond, WT_THOUSAND);
if (loop == 100) {
/*
@@ -688,13 +704,13 @@ __wt_evict_file_exclusive_on(WT_SESSION_IMPL *session)
* this point.
*/
F_SET(btree, WT_BTREE_NO_EVICTION);
- (void)__wt_atomic_add32(&cache->pass_intr, 1);
+ (void)__wt_atomic_addv32(&cache->pass_intr, 1);
WT_FULL_BARRIER();
/* Clear any existing LRU eviction walk for the file. */
WT_WITH_PASS_LOCK(session, ret,
ret = __evict_clear_walk(session));
- (void)__wt_atomic_sub32(&cache->pass_intr, 1);
+ (void)__wt_atomic_subv32(&cache->pass_intr, 1);
WT_ERR(ret);
/*
@@ -762,7 +778,6 @@ __wt_evict_file_exclusive_off(WT_SESSION_IMPL *session)
__wt_spin_unlock(session, &cache->evict_walk_lock);
}
-#define APP_EVICT_THRESHOLD 3 /* Threshold to help evict */
/*
* __evict_lru_pages --
* Get pages from the LRU queue to evict.
@@ -770,34 +785,26 @@ __wt_evict_file_exclusive_off(WT_SESSION_IMPL *session)
static int
__evict_lru_pages(WT_SESSION_IMPL *session, bool is_server)
{
- WT_CACHE *cache;
+ WT_CONNECTION_IMPL *conn;
WT_DECL_RET;
- uint64_t app_evict_percent, total_evict;
- /*
- * The server will not help evict if the threads are coping with
- * eviction workload, that is, if fewer than the threshold of the
- * pages are evicted by application threads.
- */
- if (is_server && WT_EVICT_HAS_WORKERS(session)) {
- cache = S2C(session)->cache;
- total_evict = cache->app_evicts +
- cache->server_evicts + cache->worker_evicts;
- app_evict_percent = (100 * cache->app_evicts) /
- (total_evict + 1);
- if (app_evict_percent < APP_EVICT_THRESHOLD) {
- WT_STAT_FAST_CONN_INCR(session,
- cache_eviction_server_not_evicting);
- return (0);
- }
- }
+ conn = S2C(session);
/*
* Reconcile and discard some pages: EBUSY is returned if a page fails
* eviction because it's unavailable, continue in that case.
*/
- while ((ret = __evict_page(session, is_server)) == 0 || ret == EBUSY)
- ;
+ while (F_ISSET(S2C(session), WT_CONN_EVICTION_RUN) && ret == 0)
+ if ((ret = __evict_page(session, is_server)) == EBUSY)
+ ret = 0;
+
+ /* If a worker thread found the queue empty, pause. */
+ if (ret == WT_NOTFOUND && !is_server &&
+ F_ISSET(S2C(session), WT_CONN_EVICTION_RUN)) {
+ ret = 0;
+ __wt_cond_wait(session, conn->evict_threads.wait_cond, 10000);
+ }
+
return (ret);
}
@@ -810,21 +817,45 @@ __evict_lru_walk(WT_SESSION_IMPL *session)
{
WT_CACHE *cache;
WT_DECL_RET;
- WT_EVICT_QUEUE *queue;
+ WT_EVICT_QUEUE *queue, *other_queue;
uint64_t read_gen_oldest;
- uint32_t candidates, entries, queue_index;
+ uint32_t candidates, entries;
cache = S2C(session)->cache;
+ /* Age out the score of how much the queue has been empty recently. */
+ cache->evict_empty_score = (99 * cache->evict_empty_score) / 100;
+
/* Fill the next queue (that isn't the urgent queue). */
- queue_index =
- 1 + (cache->evict_queue_fill++ % (WT_EVICT_QUEUE_MAX - 1));
- queue = &cache->evict_queues[queue_index];
+ queue = cache->evict_fill_queue;
+ other_queue = cache->evict_queues + (1 - (queue - cache->evict_queues));
+
+ /* If this queue is full, try the other one. */
+ if (__evict_queue_full(queue) && !__evict_queue_full(other_queue))
+ queue = other_queue;
+ other_queue = cache->evict_fill_queue =
+ &cache->evict_queues[1 - (queue - cache->evict_queues)];
+
+ /*
+ * If both queues are full and haven't been empty on recent refills,
+ * we're done.
+ */
+ if (__evict_queue_full(queue) &&
+ cache->evict_empty_score < WT_EVICT_EMPTY_SCORE_CUTOFF)
+ return (0);
/* Get some more pages to consider for eviction. */
- if ((ret = __evict_walk(cache->walk_session, queue_index)) != 0)
+ if ((ret = __evict_walk(cache->walk_session, queue)) != 0)
return (ret == EBUSY ? 0 : ret);
+ /* Make sure the other queue is current before locking. */
+ if (cache->evict_current_queue != other_queue) {
+ __wt_spin_lock(session, &cache->evict_queue_lock);
+ cache->evict_other_queue = queue;
+ cache->evict_current_queue = other_queue;
+ __wt_spin_unlock(session, &cache->evict_queue_lock);
+ }
+
/* Sort the list into LRU order and restart. */
__wt_spin_lock(session, &queue->evict_lock);
@@ -909,20 +940,20 @@ __evict_lru_walk(WT_SESSION_IMPL *session)
}
}
- queue->evict_current = queue->evict_queue;
- __wt_spin_unlock(session, &queue->evict_lock);
-
- /*
- * Now we can set the next queue.
- */
- __wt_spin_lock(session, &cache->evict_queue_lock);
- if (cache->evict_current_queue->evict_current == NULL)
+ if (__evict_queue_empty(queue)) {
+ /*
+ * This score varies between 0 (if the queue hasn't been empty
+ * for a long time) and 100 (if the queue has been empty the
+ * last 10 times we filled up.
+ */
+ cache->evict_empty_score = WT_MIN(100,
+ cache->evict_empty_score + WT_EVICT_EMPTY_SCORE_BUMP);
WT_STAT_FAST_CONN_INCR(session, cache_eviction_queue_empty);
- else
+ } else
WT_STAT_FAST_CONN_INCR(session, cache_eviction_queue_not_empty);
- cache->evict_current_queue = queue;
- __wt_spin_unlock(session, &cache->evict_queue_lock);
+ queue->evict_current = queue->evict_queue;
+ __wt_spin_unlock(session, &queue->evict_lock);
/*
* Signal any application or helper threads that may be waiting
@@ -938,16 +969,15 @@ __evict_lru_walk(WT_SESSION_IMPL *session)
* Fill in the array by walking the next set of pages.
*/
static int
-__evict_walk(WT_SESSION_IMPL *session, uint32_t queue_index)
+__evict_walk(WT_SESSION_IMPL *session, WT_EVICT_QUEUE *queue)
{
WT_BTREE *btree;
WT_CACHE *cache;
WT_CONNECTION_IMPL *conn;
WT_DATA_HANDLE *dhandle;
WT_DECL_RET;
- WT_EVICT_QUEUE *queue;
u_int max_entries, prev_slot, retries, slot, start_slot, spins;
- bool dhandle_locked, incr;
+ bool dhandle_locked, incr, progress;
conn = S2C(session);
cache = S2C(session)->cache;
@@ -960,7 +990,6 @@ __evict_walk(WT_SESSION_IMPL *session, uint32_t queue_index)
* Set the starting slot in the queue and the maximum pages added
* per walk.
*/
- queue = &cache->evict_queues[queue_index];
start_slot = slot = queue->evict_entries;
max_entries = WT_MIN(slot + WT_EVICT_WALK_INCR, cache->evict_slots);
@@ -1027,11 +1056,18 @@ retry: while (slot < max_entries && ret == 0) {
continue;
/*
- * Also skip files that are checkpointing or configured to
- * stick in cache until we get aggressive.
+ * Skip files that are checkpointing if we are only looking for
+ * dirty pages.
*/
- if ((btree->checkpointing != WT_CKPT_OFF ||
- btree->evict_priority != 0) &&
+ if (btree->checkpointing != WT_CKPT_OFF &&
+ !FLD_ISSET(cache->state, WT_EVICT_STATE_CLEAN))
+ continue;
+
+ /*
+ * Skip files that are configured to stick in cache until we
+ * become aggressive.
+ */
+ if (btree->evict_priority != 0 &&
!FLD_ISSET(cache->state, WT_EVICT_STATE_AGGRESSIVE))
continue;
@@ -1049,6 +1085,7 @@ retry: while (slot < max_entries && ret == 0) {
continue;
btree->evict_walk_skips = 0;
prev_slot = slot;
+ progress = false;
(void)__wt_atomic_addi32(&dhandle->session_inuse, 1);
incr = true;
@@ -1069,9 +1106,9 @@ retry: while (slot < max_entries && ret == 0) {
!__wt_spin_trylock(session, &cache->evict_walk_lock)) {
if (!F_ISSET(btree, WT_BTREE_NO_EVICTION)) {
cache->evict_file_next = dhandle;
- WT_WITH_DHANDLE(session, dhandle,
- ret = __evict_walk_file(session,
- queue_index, max_entries, &slot));
+ WT_WITH_DHANDLE(session, dhandle, ret =
+ __evict_walk_file(session, queue,
+ max_entries, &slot, &progress));
WT_ASSERT(session, session->split_gen == 0);
}
__wt_spin_unlock(session, &cache->evict_walk_lock);
@@ -1081,7 +1118,7 @@ retry: while (slot < max_entries && ret == 0) {
* If we didn't find any candidates in the file, skip it next
* time.
*/
- if (slot == prev_slot)
+ if (slot == prev_slot && !progress)
btree->evict_walk_period = WT_MIN(
WT_MAX(1, 2 * btree->evict_walk_period), 100);
else
@@ -1149,6 +1186,14 @@ __evict_push_candidate(WT_SESSION_IMPL *session,
evict->btree = S2BT(session);
evict->ref = ref;
evict->score = __evict_read_gen(evict);
+
+ /* Adjust for size when doing dirty eviction. */
+ if (FLD_ISSET(S2C(session)->cache->state, WT_EVICT_STATE_DIRTY) &&
+ evict->score != WT_READGEN_OLDEST && evict->score != UINT64_MAX &&
+ !__wt_page_is_modified(ref->page))
+ evict->score += WT_MEGABYTE -
+ WT_MIN(WT_MEGABYTE, ref->page->memory_footprint);
+
return (true);
}
@@ -1158,14 +1203,13 @@ __evict_push_candidate(WT_SESSION_IMPL *session,
*/
static int
__evict_walk_file(WT_SESSION_IMPL *session,
- uint32_t queue_index, u_int max_entries, u_int *slotp)
+ WT_EVICT_QUEUE *queue, u_int max_entries, u_int *slotp, bool *progressp)
{
WT_BTREE *btree;
WT_CACHE *cache;
WT_CONNECTION_IMPL *conn;
WT_DECL_RET;
WT_EVICT_ENTRY *end, *evict, *start;
- WT_EVICT_QUEUE *queue;
WT_PAGE *page;
WT_PAGE_MODIFY *mod;
WT_REF *ref;
@@ -1179,7 +1223,6 @@ __evict_walk_file(WT_SESSION_IMPL *session,
conn = S2C(session);
btree = S2BT(session);
cache = conn->cache;
- queue = &cache->evict_queues[queue_index];
internal_pages = restarts = 0;
/*
@@ -1288,10 +1331,13 @@ __evict_walk_file(WT_SESSION_IMPL *session,
__wt_cache_read_gen_new(session, page);
/* Pages we no longer need (clean or dirty), are found money. */
- if (page->read_gen == WT_READGEN_OLDEST) {
+ if (page->read_gen == WT_READGEN_OLDEST ||
+ page->memory_footprint >= btree->splitmempage) {
WT_STAT_FAST_CONN_INCR(
session, cache_eviction_pages_queued_oldest);
- goto fast;
+ if (__wt_page_evict_urgent(session, ref))
+ *progressp = true;
+ continue;
}
if (__wt_page_is_empty(page) ||
@@ -1421,30 +1467,67 @@ __evict_get_ref(
WT_SESSION_IMPL *session, bool is_server, WT_BTREE **btreep, WT_REF **refp)
{
WT_CACHE *cache;
+ WT_DECL_RET;
WT_EVICT_ENTRY *evict;
- WT_EVICT_QUEUE *queue, *urgent_queue;
+ WT_EVICT_QUEUE *other_queue, *queue, *urgent_queue;
uint32_t candidates;
+ bool is_app, urgent_ok;
cache = S2C(session)->cache;
- urgent_queue = &cache->evict_queues[WT_EVICT_URGENT_QUEUE];
+ is_app = !F_ISSET(session, WT_SESSION_INTERNAL);
+ urgent_ok = (!is_app && !is_server) ||
+ !WT_EVICT_HAS_WORKERS(session) ||
+ FLD_ISSET(cache->state, WT_EVICT_STATE_AGGRESSIVE);
+ urgent_queue = cache->evict_urgent_queue;
*btreep = NULL;
*refp = NULL;
- /* Avoid the LRU lock if no pages are available. */
WT_STAT_FAST_CONN_INCR(session, cache_eviction_get_ref);
- if (cache->evict_current_queue->evict_current == NULL &&
- urgent_queue->evict_current == NULL) {
+
+ /* Avoid the LRU lock if no pages are available. */
+ if (__evict_queue_empty(cache->evict_current_queue) &&
+ __evict_queue_empty(cache->evict_other_queue) &&
+ __evict_queue_empty(urgent_queue)) {
WT_STAT_FAST_CONN_INCR(session, cache_eviction_get_ref_empty);
return (WT_NOTFOUND);
}
- __wt_spin_lock(session, &cache->evict_queue_lock);
+ /*
+ * The server repopulates whenever the other queue is not full.
+ *
+ * Note that there are pathological cases where there are only enough
+ * eviction candidates in the cache to fill one queue. In that case,
+ * we will continually evict one page and attempt to refill the queues.
+ * Such cases are extremely rare in real applications.
+ */
+ if (is_server &&
+ (cache->evict_empty_score > WT_EVICT_EMPTY_SCORE_CUTOFF ||
+ __evict_queue_empty(cache->evict_fill_queue))) {
+ do {
+ if ((!urgent_ok ||
+ __evict_queue_empty(urgent_queue)) &&
+ !__evict_queue_full(cache->evict_fill_queue))
+ return (WT_NOTFOUND);
+ } while ((ret = __wt_spin_trylock(
+ session, &cache->evict_queue_lock)) == EBUSY);
+
+ WT_RET(ret);
+ } else
+ __wt_spin_lock(session, &cache->evict_queue_lock);
+
+ /*
+ * Check if the current queue needs to change.
+ * The current queue could have changed while we waited for the lock.
+ */
+ queue = cache->evict_current_queue;
+ other_queue = cache->evict_other_queue;
+ if (__evict_queue_empty(queue) && !__evict_queue_empty(other_queue)) {
+ cache->evict_current_queue = other_queue;
+ cache->evict_other_queue = queue;
+ }
/* Check the urgent queue first. */
- queue = urgent_queue->evict_current != NULL &&
- (FLD_ISSET(cache->state, WT_EVICT_STATE_AGGRESSIVE) ||
- (F_ISSET(session, WT_SESSION_INTERNAL) &&
- (!is_server || !WT_EVICT_HAS_WORKERS(session)))) ?
+ queue = urgent_ok && !__evict_queue_empty(urgent_queue) ?
urgent_queue : cache->evict_current_queue;
__wt_spin_unlock(session, &cache->evict_queue_lock);
@@ -1464,7 +1547,7 @@ __evict_get_ref(
*/
for (;;) {
/* Verify there are still pages available. */
- if (queue->evict_current == NULL || (uint32_t)
+ if (__evict_queue_empty(queue) || (uint32_t)
(queue->evict_current - queue->evict_queue) >= candidates) {
WT_STAT_FAST_CONN_INCR(
session, cache_eviction_get_ref_empty2);
@@ -1495,14 +1578,24 @@ __evict_get_ref(
* However, we can't skip entries in the urgent queue or they
* may never be found again.
*/
- if (is_server && queue != urgent_queue &&
- WT_EVICT_HAS_WORKERS(session) &&
+ if (is_server && !urgent_ok &&
!__evict_check_entry_size(session, evict)) {
--evict;
break;
}
/*
+ * Don't force application threads to evict dirty pages if they
+ * aren't stalled by the amount of dirty data in cache.
+ */
+ if (is_app && !urgent_ok &&
+ !FLD_ISSET(cache->state, WT_EVICT_STATE_DIRTY_HARD) &&
+ __wt_page_is_modified(evict->ref->page)) {
+ --evict;
+ break;
+ }
+
+ /*
* Lock the page while holding the eviction mutex to prevent
* multiple attempts to evict it. For pages that are already
* being evicted, this operation will fail and we will move on.
@@ -1539,7 +1632,7 @@ __evict_get_ref(
__wt_spin_unlock(session, &queue->evict_lock);
- return ((*refp == NULL) ? WT_NOTFOUND : 0);
+ return (*refp == NULL ? WT_NOTFOUND : 0);
}
/*
@@ -1702,11 +1795,11 @@ __wt_cache_eviction_worker(WT_SESSION_IMPL *session, bool busy, u_int pct_full)
}
/*
- * __wt_page_evict_soon --
+ * __wt_page_evict_urgent --
* Set a page to be evicted as soon as possible.
*/
-void
-__wt_page_evict_soon(WT_SESSION_IMPL *session, WT_REF *ref)
+bool
+__wt_page_evict_urgent(WT_SESSION_IMPL *session, WT_REF *ref)
{
WT_CACHE *cache;
WT_EVICT_ENTRY *evict;
@@ -1718,10 +1811,9 @@ __wt_page_evict_soon(WT_SESSION_IMPL *session, WT_REF *ref)
WT_ASSERT(session, !__wt_ref_is_root(ref));
page = ref->page;
- page->read_gen = WT_READGEN_OLDEST;
if (F_ISSET_ATOMIC(page, WT_PAGE_EVICT_LRU) ||
F_ISSET(S2BT(session), WT_BTREE_NO_EVICTION))
- return;
+ return (false);
/* Append to the urgent queue if we can. */
cache = S2C(session)->cache;
@@ -1734,12 +1826,12 @@ __wt_page_evict_soon(WT_SESSION_IMPL *session, WT_REF *ref)
goto done;
__wt_spin_lock(session, &urgent_queue->evict_lock);
- if (urgent_queue->evict_current == NULL) {
+ if (__evict_queue_empty(urgent_queue)) {
urgent_queue->evict_current = urgent_queue->evict_queue;
urgent_queue->evict_candidates = 0;
}
evict = urgent_queue->evict_queue + urgent_queue->evict_candidates;
- if (evict < urgent_queue->evict_queue + WT_EVICT_QUEUE_MAX &&
+ if (evict < urgent_queue->evict_queue + cache->evict_slots &&
__evict_push_candidate(session, urgent_queue, evict, ref)) {
++urgent_queue->evict_candidates;
queued = true;
@@ -1756,6 +1848,8 @@ done: __wt_spin_unlock(session, &cache->evict_queue_lock);
else
__wt_evict_server_wake(session);
}
+
+ return (queued);
}
/*
diff --git a/src/evict/evict_page.c b/src/evict/evict_page.c
index ff967ea0efd..972c72bbfb0 100644
--- a/src/evict/evict_page.c
+++ b/src/evict/evict_page.c
@@ -74,7 +74,7 @@ __wt_page_release_evict(WT_SESSION_IMPL *session, WT_REF *ref)
(void)__wt_atomic_addv32(&btree->evict_busy, 1);
- too_big = page->memory_footprint > btree->splitmempage;
+ too_big = page->memory_footprint >= btree->splitmempage;
if ((ret = __wt_evict(session, ref, false)) == 0) {
if (too_big)
WT_STAT_FAST_CONN_INCR(session, cache_eviction_force);
@@ -527,7 +527,9 @@ __evict_review(
else if (F_ISSET(cache, WT_CACHE_STUCK))
LF_SET(WT_EVICT_LOOKASIDE);
else if (!__wt_txn_visible_all(
- session, page->modify->update_txn))
+ session, page->modify->update_txn) ||
+ page->read_gen == WT_READGEN_OLDEST ||
+ page->memory_footprint >= S2BT(session)->splitmempage)
LF_SET(WT_EVICT_UPDATE_RESTORE);
/*
diff --git a/src/include/btree.i b/src/include/btree.i
index faaddba9dc7..1ca6426eef6 100644
--- a/src/include/btree.i
+++ b/src/include/btree.i
@@ -1232,7 +1232,7 @@ __wt_page_can_evict(
* previous version might be referenced by an internal page already
* been written in the checkpoint, leaving the checkpoint inconsistent.
*/
- if (btree->checkpointing != WT_CKPT_OFF && modified) {
+ if (modified && btree->checkpointing != WT_CKPT_OFF) {
WT_STAT_FAST_CONN_INCR(session, cache_eviction_checkpoint);
WT_STAT_FAST_DATA_INCR(session, cache_eviction_checkpoint);
return (false);
diff --git a/src/include/cache.h b/src/include/cache.h
index f00971ff7d8..c7e817fd391 100644
--- a/src/include/cache.h
+++ b/src/include/cache.h
@@ -26,8 +26,8 @@ struct __wt_evict_entry {
uint64_t score; /* Relative eviction priority */
};
-#define WT_EVICT_URGENT_QUEUE 0 /* Urgent queue index */
-#define WT_EVICT_QUEUE_MAX 3 /* Urgent plus two ordinary queues */
+#define WT_EVICT_QUEUE_MAX 3 /* Two ordinary queues plus urgent */
+#define WT_EVICT_URGENT_QUEUE 2 /* Urgent queue index */
/*
* WT_EVICT_QUEUE --
@@ -110,14 +110,19 @@ struct __wt_cache {
*/
WT_SPINLOCK evict_pass_lock; /* Eviction pass lock */
WT_SESSION_IMPL *walk_session; /* Eviction pass session */
+ WT_DATA_HANDLE
+ *evict_file_next; /* LRU next file to search */
WT_SPINLOCK evict_queue_lock; /* Eviction current queue lock */
WT_EVICT_QUEUE evict_queues[WT_EVICT_QUEUE_MAX];
- WT_EVICT_QUEUE *evict_current_queue;/* LRU current queue in use */
- uint32_t evict_queue_fill; /* LRU eviction queue index to fill */
+ WT_EVICT_QUEUE *evict_current_queue; /* LRU current queue in use */
+ WT_EVICT_QUEUE *evict_fill_queue; /* LRU next queue to fill */
+ WT_EVICT_QUEUE *evict_other_queue; /* LRU queue not in use */
+ WT_EVICT_QUEUE *evict_urgent_queue; /* LRU urgent queue */
uint32_t evict_slots; /* LRU list eviction slots */
- WT_DATA_HANDLE
- *evict_file_next; /* LRU next file to search */
- uint32_t evict_max_refs_per_file;/* LRU pages per file per pass */
+#define WT_EVICT_EMPTY_SCORE_BUMP 10
+#define WT_EVICT_EMPTY_SCORE_CUTOFF 10
+ uint32_t evict_empty_score; /* LRU score of how often queues are
+ empty on refill. */
/*
* Cache pool information.
@@ -139,15 +144,17 @@ struct __wt_cache {
#define WT_EVICT_STATE_AGGRESSIVE 0x01 /* Eviction isn't making progress:
try harder */
#define WT_EVICT_STATE_CLEAN 0x02 /* Evict clean pages */
-#define WT_EVICT_STATE_DIRTY 0x04 /* Evict dirty pages */
-#define WT_EVICT_STATE_SCRUB 0x08 /* Scrub dirty pages pages */
-#define WT_EVICT_STATE_URGENT 0x10 /* Pages are in the urgent queue */
+#define WT_EVICT_STATE_CLEAN_HARD 0x04 /* Clean % blocking app threads */
+#define WT_EVICT_STATE_DIRTY 0x08 /* Evict dirty pages */
+#define WT_EVICT_STATE_DIRTY_HARD 0x10 /* Dirty % blocking app threads */
+#define WT_EVICT_STATE_SCRUB 0x20 /* Scrub dirty pages pages */
+#define WT_EVICT_STATE_URGENT 0x40 /* Pages are in the urgent queue */
#define WT_EVICT_STATE_ALL (WT_EVICT_STATE_CLEAN | WT_EVICT_STATE_DIRTY)
uint32_t state;
/*
* Pass interrupt counter.
*/
- uint32_t pass_intr; /* Interrupt eviction pass. */
+ volatile uint32_t pass_intr; /* Interrupt eviction pass. */
/*
* Flags.
diff --git a/src/include/cache.i b/src/include/cache.i
index 1163826422c..155b1a7ab3d 100644
--- a/src/include/cache.i
+++ b/src/include/cache.i
@@ -68,6 +68,18 @@ __wt_cache_read_gen_new(WT_SESSION_IMPL *session, WT_PAGE *page)
}
/*
+ * __wt_page_evict_soon --
+ * Set a page to be evicted as soon as possible.
+ */
+static inline void
+__wt_page_evict_soon(WT_SESSION_IMPL *session, WT_REF *ref)
+{
+ WT_UNUSED(session);
+
+ ref->page->read_gen = WT_READGEN_OLDEST;
+}
+
+/*
* __wt_cache_pages_inuse --
* Return the number of pages in use.
*/
@@ -188,7 +200,7 @@ __wt_eviction_needed(WT_SESSION_IMPL *session, u_int *pct_fullp)
WT_CONNECTION_IMPL *conn;
WT_CACHE *cache;
uint64_t bytes_inuse, bytes_max;
- u_int pct_full;
+ u_int pct_dirty, pct_full;
conn = S2C(session);
cache = conn->cache;
@@ -212,24 +224,16 @@ __wt_eviction_needed(WT_SESSION_IMPL *session, u_int *pct_fullp)
* we involve the application thread.
*/
pct_full = (u_int)((100 * bytes_inuse) / bytes_max);
- if (pct_fullp != NULL)
- *pct_fullp = pct_full;
-
- if (pct_full > cache->eviction_trigger)
- return (true);
+ pct_dirty =
+ (u_int)((100 * __wt_cache_dirty_leaf_inuse(cache)) / bytes_max);
- /*
- * Check if there are too many dirty bytes in cache.
- *
- * We try to avoid penalizing read-only operations by only checking the
- * dirty limit once a transaction ID has been allocated, or if the last
- * transaction did an update.
- */
- if (__wt_cache_dirty_leaf_inuse(cache) >
- (cache->eviction_dirty_trigger * bytes_max) / 100)
- return (true);
+ if (pct_fullp != NULL)
+ *pct_fullp = (u_int)WT_MAX(0, 100 - WT_MIN(
+ (int)cache->eviction_trigger - (int)pct_full,
+ (int)cache->eviction_dirty_trigger - (int)pct_dirty));
- return (false);
+ return (pct_full >= cache->eviction_trigger ||
+ pct_dirty >= cache->eviction_dirty_trigger);
}
/*
diff --git a/src/include/extern.h b/src/include/extern.h
index 72e7f1aa9ec..2992a97b727 100644
--- a/src/include/extern.h
+++ b/src/include/extern.h
@@ -345,7 +345,7 @@ extern int __wt_evict_destroy(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBU
extern int __wt_evict_file_exclusive_on(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern void __wt_evict_file_exclusive_off(WT_SESSION_IMPL *session);
extern int __wt_cache_eviction_worker(WT_SESSION_IMPL *session, bool busy, u_int pct_full) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
-extern void __wt_page_evict_soon(WT_SESSION_IMPL *session, WT_REF *ref);
+extern bool __wt_page_evict_urgent(WT_SESSION_IMPL *session, WT_REF *ref);
extern void __wt_evict_priority_set(WT_SESSION_IMPL *session, uint64_t v);
extern void __wt_evict_priority_clear(WT_SESSION_IMPL *session);
extern int __wt_cache_dump(WT_SESSION_IMPL *session, const char *ofile) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
diff --git a/src/include/stat.h b/src/include/stat.h
index 1df24382236..e0d0a6eb780 100644
--- a/src/include/stat.h
+++ b/src/include/stat.h
@@ -289,10 +289,10 @@ struct __wt_connection_stats {
int64_t cache_eviction_queue_empty;
int64_t cache_eviction_queue_not_empty;
int64_t cache_eviction_server_evicting;
- int64_t cache_eviction_server_not_evicting;
int64_t cache_eviction_server_toobig;
int64_t cache_eviction_server_slept;
int64_t cache_eviction_slow;
+ int64_t cache_eviction_state;
int64_t cache_eviction_worker_evicting;
int64_t cache_eviction_force_fail;
int64_t cache_eviction_walks_active;
diff --git a/src/include/wiredtiger.in b/src/include/wiredtiger.in
index f915f9de3d6..10141cd34c1 100644
--- a/src/include/wiredtiger.in
+++ b/src/include/wiredtiger.in
@@ -4289,15 +4289,15 @@ extern int wiredtiger_extension_terminate(WT_CONNECTION *connection);
#define WT_STAT_CONN_CACHE_EVICTION_QUEUE_NOT_EMPTY 1042
/*! cache: eviction server evicting pages */
#define WT_STAT_CONN_CACHE_EVICTION_SERVER_EVICTING 1043
-/*! cache: eviction server populating queue, but not evicting pages */
-#define WT_STAT_CONN_CACHE_EVICTION_SERVER_NOT_EVICTING 1044
/*! cache: eviction server skipped very large page */
-#define WT_STAT_CONN_CACHE_EVICTION_SERVER_TOOBIG 1045
+#define WT_STAT_CONN_CACHE_EVICTION_SERVER_TOOBIG 1044
/*! cache: eviction server slept, because we did not make progress with
* eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_SERVER_SLEPT 1046
+#define WT_STAT_CONN_CACHE_EVICTION_SERVER_SLEPT 1045
/*! cache: eviction server unable to reach eviction goal */
-#define WT_STAT_CONN_CACHE_EVICTION_SLOW 1047
+#define WT_STAT_CONN_CACHE_EVICTION_SLOW 1046
+/*! cache: eviction state */
+#define WT_STAT_CONN_CACHE_EVICTION_STATE 1047
/*! cache: eviction worker thread evicting pages */
#define WT_STAT_CONN_CACHE_EVICTION_WORKER_EVICTING 1048
/*! cache: failed eviction of pages that exceeded the in-memory maximum */
diff --git a/src/support/stat.c b/src/support/stat.c
index 49cb3bebc07..8927be862c1 100644
--- a/src/support/stat.c
+++ b/src/support/stat.c
@@ -562,10 +562,10 @@ static const char * const __stats_connection_desc[] = {
"cache: eviction server candidate queue empty when topping up",
"cache: eviction server candidate queue not empty when topping up",
"cache: eviction server evicting pages",
- "cache: eviction server populating queue, but not evicting pages",
"cache: eviction server skipped very large page",
"cache: eviction server slept, because we did not make progress with eviction",
"cache: eviction server unable to reach eviction goal",
+ "cache: eviction state",
"cache: eviction worker thread evicting pages",
"cache: failed eviction of pages that exceeded the in-memory maximum",
"cache: files with active eviction walks",
@@ -805,10 +805,10 @@ __wt_stat_connection_clear_single(WT_CONNECTION_STATS *stats)
stats->cache_eviction_queue_empty = 0;
stats->cache_eviction_queue_not_empty = 0;
stats->cache_eviction_server_evicting = 0;
- stats->cache_eviction_server_not_evicting = 0;
stats->cache_eviction_server_toobig = 0;
stats->cache_eviction_server_slept = 0;
stats->cache_eviction_slow = 0;
+ /* not clearing cache_eviction_state */
stats->cache_eviction_worker_evicting = 0;
stats->cache_eviction_force_fail = 0;
/* not clearing cache_eviction_walks_active */
@@ -905,9 +905,9 @@ __wt_stat_connection_clear_single(WT_CONNECTION_STATS *stats)
stats->log_write_lsn = 0;
stats->log_write_lsn_skip = 0;
stats->log_sync = 0;
- stats->log_sync_duration = 0;
+ /* not clearing log_sync_duration */
stats->log_sync_dir = 0;
- stats->log_sync_dir_duration = 0;
+ /* not clearing log_sync_dir_duration */
stats->log_writes = 0;
stats->log_slot_consolidated = 0;
/* not clearing log_max_filesize */
@@ -1049,13 +1049,12 @@ __wt_stat_connection_aggregate(
WT_STAT_READ(from, cache_eviction_queue_not_empty);
to->cache_eviction_server_evicting +=
WT_STAT_READ(from, cache_eviction_server_evicting);
- to->cache_eviction_server_not_evicting +=
- WT_STAT_READ(from, cache_eviction_server_not_evicting);
to->cache_eviction_server_toobig +=
WT_STAT_READ(from, cache_eviction_server_toobig);
to->cache_eviction_server_slept +=
WT_STAT_READ(from, cache_eviction_server_slept);
to->cache_eviction_slow += WT_STAT_READ(from, cache_eviction_slow);
+ to->cache_eviction_state += WT_STAT_READ(from, cache_eviction_state);
to->cache_eviction_worker_evicting +=
WT_STAT_READ(from, cache_eviction_worker_evicting);
to->cache_eviction_force_fail +=
diff --git a/src/txn/txn_ckpt.c b/src/txn/txn_ckpt.c
index 9a062611422..5406367c372 100644
--- a/src/txn/txn_ckpt.c
+++ b/src/txn/txn_ckpt.c
@@ -732,7 +732,7 @@ __txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[])
WT_ERR(__wt_epoch(session, &fsync_stop));
fsync_duration_usecs = WT_TIMEDIFF_US(fsync_stop, fsync_start);
WT_STAT_FAST_CONN_INCR(session, txn_checkpoint_fsync_post);
- WT_STAT_FAST_CONN_INCRV(session,
+ WT_STAT_FAST_CONN_SET(session,
txn_checkpoint_fsync_post_duration, fsync_duration_usecs);
WT_ERR(__checkpoint_verbose_track(session,
diff --git a/test/csuite/wt2834_join_bloom_fix/main.c b/test/csuite/wt2834_join_bloom_fix/main.c
index f080be09163..1e2d919d3c7 100644
--- a/test/csuite/wt2834_join_bloom_fix/main.c
+++ b/test/csuite/wt2834_join_bloom_fix/main.c
@@ -44,7 +44,7 @@ void (*custom_die)(void) = NULL;
#define N_RECORDS 100000
#define N_INSERT 1000000
-void *populate(TEST_OPTS *opts);
+void populate(TEST_OPTS *opts);
int
main(int argc, char *argv[])
@@ -110,8 +110,6 @@ main(int argc, char *argv[])
testutil_check(opts->conn->open_session(
opts->conn, NULL, NULL, &session));
- testutil_check(session->begin_transaction(session,
- "isolation=snapshot"));
testutil_check(session->open_cursor(session,
posturi, NULL, NULL, &postcur));
testutil_check(session->open_cursor(session,
@@ -161,7 +159,7 @@ main(int argc, char *argv[])
return (0);
}
-void *populate(TEST_OPTS *opts)
+void populate(TEST_OPTS *opts)
{
WT_CURSOR *maincur;
WT_SESSION *session;
@@ -198,5 +196,4 @@ void *populate(TEST_OPTS *opts)
}
maincur->close(maincur);
session->close(session, NULL);
- return (NULL);
}
diff --git a/tools/wtstats/stat_data.py b/tools/wtstats/stat_data.py
index b93f2449c63..1eb60c9d513 100644
--- a/tools/wtstats/stat_data.py
+++ b/tools/wtstats/stat_data.py
@@ -7,6 +7,7 @@ no_scale_per_second_list = [
'cache: bytes currently in the cache',
'cache: bytes not belonging to page images in the cache',
'cache: eviction currently operating in aggressive mode',
+ 'cache: eviction state',
'cache: files with active eviction walks',
'cache: hazard pointer maximum array length',
'cache: maximum bytes configured',
@@ -20,6 +21,8 @@ no_scale_per_second_list = [
'cache: tracked dirty pages in the cache',
'connection: files currently open',
'data-handle: connection data handles currently active',
+ 'log: log sync time duration (usecs)',
+ 'log: log sync_dir time duration (usecs)',
'log: maximum log file size',
'log: number of pre-allocated log files to create',
'log: total log buffer size',
@@ -100,6 +103,7 @@ no_clear_list = [
'cache: bytes currently in the cache',
'cache: bytes not belonging to page images in the cache',
'cache: eviction currently operating in aggressive mode',
+ 'cache: eviction state',
'cache: files with active eviction walks',
'cache: maximum bytes configured',
'cache: maximum page size at eviction',
@@ -111,6 +115,8 @@ no_clear_list = [
'cache: tracked dirty pages in the cache',
'connection: files currently open',
'data-handle: connection data handles currently active',
+ 'log: log sync time duration (usecs)',
+ 'log: log sync_dir time duration (usecs)',
'log: maximum log file size',
'log: number of pre-allocated log files to create',
'log: total log buffer size',