summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@mongodb.com>2016-09-15 17:33:26 +1000
committerAlex Gorrod <alexander.gorrod@mongodb.com>2016-09-15 17:33:26 +1000
commit1c4d75fe92716950d50a05ddceda5b0cfbedbb17 (patch)
tree1f0d7e9ebad7c16a71962942fb0cf44ca29f6b3d
parent10dd36a9bf507e13d2d17ff72d9d55a88aae2f12 (diff)
downloadmongo-1c4d75fe92716950d50a05ddceda5b0cfbedbb17.tar.gz
WT-2913 Re-sort eviction queues if we find no new candidates. (#3043)
We could be in a situation with a tiny number of pages in cache, all of which are already queued. The queue needs to be re-sorted so that some of those entries can become candidates. This caused hangs in some test/format configs.
-rw-r--r--src/evict/evict_lru.c42
1 files changed, 20 insertions, 22 deletions
diff --git a/src/evict/evict_lru.c b/src/evict/evict_lru.c
index 75b8e746515..5c622794dc2 100644
--- a/src/evict/evict_lru.c
+++ b/src/evict/evict_lru.c
@@ -876,27 +876,25 @@ __evict_lru_walk(WT_SESSION_IMPL *session)
return (0);
/* Get some more pages to consider for eviction. */
- switch (ret = __evict_walk(cache->walk_session, queue)) {
- case 0:
- break;
- case EBUSY:
- return (0);
- case WT_NOTFOUND:
- /*
- * If we found no pages at all during the walk, something is
- * wrong. Be more aggressive next time.
- */
+ if ((ret = __evict_walk(cache->walk_session, queue)) == EBUSY)
+ return (0); /* An interrupt was requested, give up. */
+ WT_RET_NOTFOUND_OK(ret);
+
+ /*
+ * If we found no pages at all during the walk, something is wrong.
+ * Be more aggressive next time.
+ *
+ * Continue on to sort the queue, in case there are pages left from a
+ * previous walk.
+ */
+ if (ret == WT_NOTFOUND) {
if (F_ISSET(cache,
WT_CACHE_EVICT_CLEAN_HARD | WT_CACHE_EVICT_DIRTY_HARD))
cache->evict_aggressive_score = WT_MIN(
cache->evict_aggressive_score + WT_EVICT_SCORE_BUMP,
WT_EVICT_SCORE_MAX);
- WT_STAT_CONN_SET(session,
- cache_eviction_aggressive_set,
+ WT_STAT_CONN_SET(session, cache_eviction_aggressive_set,
cache->evict_aggressive_score);
- return (0);
- default:
- return (ret);
}
/*
@@ -932,6 +930,7 @@ __evict_lru_walk(WT_SESSION_IMPL *session)
qsort(queue->evict_queue,
entries, sizeof(WT_EVICT_ENTRY), __evict_lru_cmp);
+ /* Trim empty entries from the end. */
while (entries > 0 && queue->evict_queue[entries - 1].ref == NULL)
--entries;
@@ -941,8 +940,7 @@ __evict_lru_walk(WT_SESSION_IMPL *session)
* candidates so we never end up with more candidates than entries.
*/
while (entries > WT_EVICT_WALK_BASE)
- __evict_list_clear(session,
- &queue->evict_queue[--entries]);
+ __evict_list_clear(session, &queue->evict_queue[--entries]);
queue->evict_entries = entries;
@@ -963,14 +961,14 @@ __evict_lru_walk(WT_SESSION_IMPL *session)
queue->evict_candidates = entries;
else {
/*
- * Find the oldest read generation we have in the queue, used
- * to set the initial value for pages read into the system.
+ * Find the oldest read generation apart from WT_READGEN_OLDEST
+ * that we have in the queue, used to set the initial value for
+ * pages read into the system.
* The queue is sorted, find the first "normal" generation.
*/
read_gen_oldest = WT_READGEN_OLDEST;
for (candidates = 0; candidates < entries; ++candidates) {
- read_gen_oldest =
- queue->evict_queue[candidates].score;
+ read_gen_oldest = queue->evict_queue[candidates].score;
if (read_gen_oldest != WT_READGEN_OLDEST)
break;
}
@@ -1355,7 +1353,7 @@ __evict_walk_file(WT_SESSION_IMPL *session,
* no good eviction candidates can be found. Abandon the walk
* if we get into that situation.
*/
- give_up = pages_seen > 100 &&
+ give_up = !__wt_cache_aggressive(session) && pages_seen > 100 &&
(pages_queued == 0 || (pages_seen / pages_queued) >
(10 * total_slots / target_pages));
if (give_up)