summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@mongodb.com>2016-09-16 14:20:37 +1000
committerGitHub <noreply@github.com>2016-09-16 14:20:37 +1000
commitd318b8a5370f7182beeab4124cee04fdce271608 (patch)
tree80eb6f40e9bf72439cdf7c9634bbb665ac0ed13c
parent0bf6b4d9ffc468920c3432bf77da1da940576af4 (diff)
downloadmongo-d318b8a5370f7182beeab4124cee04fdce271608.tar.gz
WT-2910 When running in-memory, only evict dirty pages. (#3044)
* Don't relax the clean / dirty requirements when we get aggressive: if application threads are blocked by the dirty limit, evicting a clean page doesn't unblock them so there's no point trying. * Sanity check dirty eviction limits: once the cache is full, we should evict both clean and dirty pages.
-rw-r--r--src/conn/conn_cache.c14
-rw-r--r--src/evict/evict_lru.c33
2 files changed, 42 insertions, 5 deletions
diff --git a/src/conn/conn_cache.c b/src/conn/conn_cache.c
index 7e94e9e87dc..6788b1f7f47 100644
--- a/src/conn/conn_cache.c
+++ b/src/conn/conn_cache.c
@@ -56,6 +56,13 @@ __cache_config_local(WT_SESSION_IMPL *session, bool shared, const char *cfg[])
cache->eviction_dirty_target = (u_int)cval.val;
/*
+ * Don't allow the dirty target to be larger than the overall
+ * target.
+ */
+ if (cache->eviction_dirty_target > cache->eviction_target)
+ cache->eviction_dirty_target = cache->eviction_target;
+
+ /*
* Sanity check the checkpoint target: don't allow a value
* lower than the dirty target.
*/
@@ -68,6 +75,13 @@ __cache_config_local(WT_SESSION_IMPL *session, bool shared, const char *cfg[])
WT_RET(__wt_config_gets(
session, cfg, "eviction_dirty_trigger", &cval));
cache->eviction_dirty_trigger = (u_int)cval.val;
+
+ /*
+ * Don't allow the dirty trigger to be larger than the overall
+ * trigger or we can get stuck with a cache full of dirty data.
+ */
+ if (cache->eviction_dirty_trigger > cache->eviction_trigger)
+ cache->eviction_dirty_trigger = cache->eviction_trigger;
}
WT_RET(__wt_config_gets(session, cfg, "eviction.threads_max", &cval));
diff --git a/src/evict/evict_lru.c b/src/evict/evict_lru.c
index cc4d8ea1e08..843249b695d 100644
--- a/src/evict/evict_lru.c
+++ b/src/evict/evict_lru.c
@@ -468,6 +468,14 @@ __evict_update_work(WT_SESSION_IMPL *session)
F_SET(cache, WT_CACHE_EVICT_DIRTY_HARD);
/*
+ * If application threads are blocked by the total volume of data in
+ * cache, try dirty pages as well.
+ */
+ if (__wt_cache_aggressive(session) &&
+ F_ISSET(cache, WT_CACHE_EVICT_CLEAN_HARD))
+ F_SET(cache, WT_CACHE_EVICT_DIRTY);
+
+ /*
* Scrub dirty pages and keep them in cache if we are less than half
* way to the clean or dirty trigger.
*/
@@ -477,6 +485,18 @@ __evict_update_work(WT_SESSION_IMPL *session)
bytes_max) / 200)
F_SET(cache, WT_CACHE_EVICT_SCRUB);
+ /*
+ * With an in-memory cache, we only do dirty eviction in order to scrub
+ * pages.
+ */
+ if (F_ISSET(conn, WT_CONN_IN_MEMORY)) {
+ if (F_ISSET(cache, WT_CACHE_EVICT_CLEAN))
+ F_SET(cache, WT_CACHE_EVICT_DIRTY);
+ if (F_ISSET(cache, WT_CACHE_EVICT_CLEAN_HARD))
+ F_SET(cache, WT_CACHE_EVICT_DIRTY_HARD);
+ F_CLR(cache, WT_CACHE_EVICT_CLEAN | WT_CACHE_EVICT_CLEAN_HARD);
+ }
+
WT_STAT_CONN_SET(session, cache_eviction_state,
F_MASK(cache, WT_CACHE_EVICT_MASK));
@@ -1348,7 +1368,7 @@ __evict_walk_file(WT_SESSION_IMPL *session,
ret = __wt_tree_walk_count(
session, &btree->evict_ref, &refs_walked, walk_flags)) {
/*
- * Check whether we're finding a good ration of candidates vs
+ * Check whether we're finding a good ratio of candidates vs
* pages seen. Some workloads create "deserts" in trees where
* no good eviction candidates can be found. Abandon the walk
* if we get into that situation.
@@ -1402,20 +1422,23 @@ __evict_walk_file(WT_SESSION_IMPL *session,
continue;
}
+ /* Pages that are empty or from dead trees are also good. */
if (__wt_page_is_empty(page) ||
- F_ISSET(session->dhandle, WT_DHANDLE_DEAD) ||
- __wt_cache_aggressive(session))
+ F_ISSET(session->dhandle, WT_DHANDLE_DEAD))
goto fast;
/* Skip clean pages if appropriate. */
- if (!modified && (F_ISSET(conn, WT_CONN_IN_MEMORY) ||
- !F_ISSET(cache, WT_CACHE_EVICT_CLEAN)))
+ if (!modified && !F_ISSET(cache, WT_CACHE_EVICT_CLEAN))
continue;
/* Skip dirty pages if appropriate. */
if (modified && !F_ISSET(cache, WT_CACHE_EVICT_DIRTY))
continue;
+ /* If eviction gets aggressive, anything else is fair game. */
+ if (__wt_cache_aggressive(session))
+ goto fast;
+
/* Limit internal pages to 50% of the total. */
if (WT_PAGE_IS_INTERNAL(page) &&
internal_pages >= (int)(evict - start) / 2)