diff options
-rw-r--r-- | dist/api_data.py | 30 | ||||
-rw-r--r-- | dist/flags.py | 4 | ||||
-rw-r--r-- | dist/stat_data.py | 2 | ||||
-rw-r--r-- | src/btree/bt_curnext.c | 2 | ||||
-rw-r--r-- | src/btree/bt_curprev.c | 2 | ||||
-rw-r--r-- | src/btree/bt_discard.c | 4 | ||||
-rw-r--r-- | src/btree/bt_page.c | 1 | ||||
-rw-r--r-- | src/btree/bt_read.c | 14 | ||||
-rw-r--r-- | src/btree/bt_split.c | 2 | ||||
-rw-r--r-- | src/btree/bt_walk.c | 2 | ||||
-rw-r--r-- | src/btree/row_srch.c | 2 | ||||
-rw-r--r-- | src/conn/conn_cache.c | 25 | ||||
-rw-r--r-- | src/evict/evict_lru.c | 331 | ||||
-rw-r--r-- | src/evict/evict_page.c | 114 | ||||
-rw-r--r-- | src/include/btree.i | 109 | ||||
-rw-r--r-- | src/include/cache.h | 25 | ||||
-rw-r--r-- | src/include/cache.i | 63 | ||||
-rw-r--r-- | src/include/cursor.i | 2 | ||||
-rw-r--r-- | src/include/extern.h | 2 | ||||
-rw-r--r-- | src/include/flags.h | 10 | ||||
-rw-r--r-- | src/include/stat.h | 2 | ||||
-rw-r--r-- | src/include/wiredtiger.in | 328 | ||||
-rw-r--r-- | src/support/stat.c | 6 | ||||
-rw-r--r-- | src/txn/txn_ckpt.c | 3 | ||||
-rw-r--r-- | tools/wtstats/stat_data.py | 4 |
25 files changed, 607 insertions, 482 deletions
diff --git a/dist/api_data.py b/dist/api_data.py index 90b1c8378a2..960f800a44d 100644 --- a/dist/api_data.py +++ b/dist/api_data.py @@ -388,6 +388,21 @@ connection_runtime_config = [ ]), Config('error_prefix', '', r''' prefix string for error messages'''), + Config('eviction', '', r''' + eviction configuration options.''', + type='category', subconfig=[ + Config('threads_max', '1', r''' + maximum number of threads WiredTiger will start to help evict + pages from cache. The number of threads started will vary + depending on the current eviction load. Each eviction worker + thread uses a session from the configured session_max''', + min=1, max=20), + Config('threads_min', '1', r''' + minimum number of threads WiredTiger will start to help evict + pages from cache. The number of threads currently running will + vary depending on the current eviction load''', + min=1, max=20), + ]), Config('eviction_dirty_target', '80', r''' continue evicting until the cache has less dirty memory than the value, as a percentage of the total cache size. Dirty pages will @@ -472,21 +487,6 @@ connection_runtime_config = [ Config('lsm_merge', 'true', r''' merge LSM chunks where possible (deprecated)''', type='boolean', undoc=True), - Config('eviction', '', r''' - eviction configuration options.''', - type='category', subconfig=[ - Config('threads_max', '1', r''' - maximum number of threads WiredTiger will start to help evict - pages from cache. The number of threads started will vary - depending on the current eviction load. Each eviction worker - thread uses a session from the configured session_max''', - min=1, max=20), - Config('threads_min', '1', r''' - minimum number of threads WiredTiger will start to help evict - pages from cache. The number of threads currently running will - vary depending on the current eviction load''', - min=1, max=20), - ]), Config('shared_cache', '', r''' shared cache configuration options. A database should configure either a cache_size or a shared_cache not both. Enabling a diff --git a/dist/flags.py b/dist/flags.py index b5f36fb707a..b661fa348fa 100644 --- a/dist/flags.py +++ b/dist/flags.py @@ -37,10 +37,12 @@ flags = { 'READ_WONT_NEED', ], 'rec_write' : [ + 'EVICTING', + 'EVICT_CLEAN', 'EVICT_IN_MEMORY', + 'EVICT_INMEM_SPLIT', 'EVICT_LOOKASIDE', 'EVICT_UPDATE_RESTORE', - 'EVICTING', 'VISIBILITY_ERR', ], 'txn_log_checkpoint' : [ diff --git a/dist/stat_data.py b/dist/stat_data.py index 2dc828d8afb..4721f3e629f 100644 --- a/dist/stat_data.py +++ b/dist/stat_data.py @@ -168,10 +168,12 @@ connection_stats = [ # Cache and eviction statistics ########################################## CacheStat('cache_bytes_dirty', 'tracked dirty bytes in the cache', 'no_clear,no_scale,size'), + CacheStat('cache_bytes_image', 'bytes belonging to page images in the cache', 'no_clear,no_scale,size'), CacheStat('cache_bytes_internal', 'tracked bytes belonging to internal pages in the cache', 'no_clear,no_scale,size'), CacheStat('cache_bytes_inuse', 'bytes currently in the cache', 'no_clear,no_scale,size'), CacheStat('cache_bytes_leaf', 'tracked bytes belonging to leaf pages in the cache', 'no_clear,no_scale,size'), CacheStat('cache_bytes_max', 'maximum bytes configured', 'no_clear,no_scale,size'), + CacheStat('cache_bytes_other', 'bytes not belonging to page images in the cache', 'no_clear,no_scale,size'), CacheStat('cache_bytes_overflow', 'tracked bytes belonging to overflow pages in the cache', 'no_clear,no_scale,size'), CacheStat('cache_bytes_read', 'bytes read into cache', 'size'), CacheStat('cache_bytes_write', 'bytes written from cache', 'size'), diff --git a/src/btree/bt_curnext.c b/src/btree/bt_curnext.c index 70b3ba56e31..5e6c3c7e9de 100644 --- a/src/btree/bt_curnext.c +++ b/src/btree/bt_curnext.c @@ -661,7 +661,7 @@ __wt_btcur_next(WT_CURSOR_BTREE *cbt, bool truncating) if (page != NULL && (cbt->page_deleted_count > WT_BTREE_DELETE_THRESHOLD || (newpage && cbt->page_deleted_count > 0))) - __wt_page_evict_soon(page); + __wt_page_evict_soon(session, cbt->ref); cbt->page_deleted_count = 0; WT_ERR(__wt_tree_walk(session, &cbt->ref, flags)); diff --git a/src/btree/bt_curprev.c b/src/btree/bt_curprev.c index 872f648446c..c92ef41626b 100644 --- a/src/btree/bt_curprev.c +++ b/src/btree/bt_curprev.c @@ -619,7 +619,7 @@ __wt_btcur_prev(WT_CURSOR_BTREE *cbt, bool truncating) if (page != NULL && (cbt->page_deleted_count > WT_BTREE_DELETE_THRESHOLD || (newpage && cbt->page_deleted_count > 0))) - __wt_page_evict_soon(page); + __wt_page_evict_soon(session, cbt->ref); cbt->page_deleted_count = 0; WT_ERR(__wt_tree_walk(session, &cbt->ref, flags)); diff --git a/src/btree/bt_discard.c b/src/btree/bt_discard.c index a00bb7dc2b5..965aec16fc2 100644 --- a/src/btree/bt_discard.c +++ b/src/btree/bt_discard.c @@ -131,8 +131,10 @@ __wt_page_out(WT_SESSION_IMPL *session, WT_PAGE **pagep) /* Discard any disk image. */ dsk = (WT_PAGE_HEADER *)page->dsk; - if (F_ISSET_ATOMIC(page, WT_PAGE_DISK_ALLOC)) + if (F_ISSET_ATOMIC(page, WT_PAGE_DISK_ALLOC)) { + __wt_cache_page_image_decr(session, dsk->mem_size); __wt_overwrite_and_free_len(session, dsk, dsk->mem_size); + } /* Discard any mapped image. */ if (F_ISSET_ATOMIC(page, WT_PAGE_DISK_MAPPED)) diff --git a/src/btree/bt_page.c b/src/btree/bt_page.c index 00ec8aa4494..89e5f428628 100644 --- a/src/btree/bt_page.c +++ b/src/btree/bt_page.c @@ -219,6 +219,7 @@ __wt_page_inmem(WT_SESSION_IMPL *session, WT_REF *ref, /* Update the page's in-memory size and the cache statistics. */ __wt_cache_page_inmem_incr(session, page, size); + __wt_cache_page_image_incr(session, dsk->mem_size); /* Link the new internal page to the parent. */ if (ref != NULL) { diff --git a/src/btree/bt_read.c b/src/btree/bt_read.c index 086500c8b2f..23aa86a3e40 100644 --- a/src/btree/bt_read.c +++ b/src/btree/bt_read.c @@ -296,7 +296,7 @@ err: WT_TRET(__wt_las_cursor_close(session, &cursor, session_flags)); * __evict_force_check -- * Check if a page matches the criteria for forced eviction. */ -static int +static bool __evict_force_check(WT_SESSION_IMPL *session, WT_REF *ref) { WT_BTREE *btree; @@ -307,26 +307,26 @@ __evict_force_check(WT_SESSION_IMPL *session, WT_REF *ref) /* Leaf pages only. */ if (WT_PAGE_IS_INTERNAL(page)) - return (0); + return (false); /* * It's hard to imagine a page with a huge memory footprint that has * never been modified, but check to be sure. */ if (page->modify == NULL) - return (0); + return (false); /* Pages are usually small enough, check that first. */ if (page->memory_footprint < btree->splitmempage) - return (0); + return (false); else if (page->memory_footprint < btree->maxmempage) return (__wt_leaf_page_can_split(session, page)); /* Trigger eviction on the next page release. */ - __wt_page_evict_soon(page); + __wt_page_evict_soon(session, ref); /* Bump the oldest ID, we're about to do some visibility checks. */ - WT_RET(__wt_txn_update_oldest(session, 0)); + (void)__wt_txn_update_oldest(session, 0); /* If eviction cannot succeed, don't try. */ return (__wt_page_can_evict(session, ref, NULL)); @@ -595,7 +595,7 @@ __wt_page_in_func(WT_SESSION_IMPL *session, WT_REF *ref, uint32_t flags page = ref->page; if (page->read_gen == WT_READGEN_NOTSET) { if (evict_soon) - __wt_page_evict_soon(page); + __wt_page_evict_soon(session, ref); else __wt_cache_read_gen_new(session, page); } else if (!LF_ISSET(WT_READ_NO_GEN)) diff --git a/src/btree/bt_split.c b/src/btree/bt_split.c index 0461f695e74..b58c44f3170 100644 --- a/src/btree/bt_split.c +++ b/src/btree/bt_split.c @@ -794,7 +794,7 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, WT_REF **ref_new, */ if (result_entries == 0) { empty_parent = true; - __wt_page_evict_soon(parent); + __wt_page_evict_soon(session, parent->pg_intl_parent_ref); goto err; } diff --git a/src/btree/bt_walk.c b/src/btree/bt_walk.c index bb8a750d848..330480f7f86 100644 --- a/src/btree/bt_walk.c +++ b/src/btree/bt_walk.c @@ -386,7 +386,7 @@ restart: /* * eviction. */ if (empty_internal && pindex->entries > 1) { - __wt_page_evict_soon(ref->page); + __wt_page_evict_soon(session, ref); empty_internal = false; } diff --git a/src/btree/row_srch.c b/src/btree/row_srch.c index 4afcd74520f..d4e82c458d4 100644 --- a/src/btree/row_srch.c +++ b/src/btree/row_srch.c @@ -775,7 +775,7 @@ __wt_row_random_leaf(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt) * traversing the skip list each time accumulates to real time. */ if (samples > 5000) - __wt_page_evict_soon(page); + __wt_page_evict_soon(session, cbt->ref); return (0); } diff --git a/src/conn/conn_cache.c b/src/conn/conn_cache.c index aaed18f0323..4fccac88bc1 100644 --- a/src/conn/conn_cache.c +++ b/src/conn/conn_cache.c @@ -176,6 +176,10 @@ __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]; + /* * We get/set some values in the cache statistics (rather than have * two copies), configure them. @@ -213,21 +217,25 @@ __wt_cache_stats_update(WT_SESSION_IMPL *session) WT_STAT_SET(session, stats, cache_bytes_max, conn->cache_size); WT_STAT_SET(session, stats, cache_bytes_inuse, inuse); - WT_STAT_SET(session, stats, cache_overhead, cache->overhead_pct); - WT_STAT_SET( - session, stats, cache_pages_inuse, __wt_cache_pages_inuse(cache)); + WT_STAT_SET( session, stats, cache_bytes_dirty, __wt_cache_dirty_inuse(cache)); - WT_STAT_SET(session, stats, - cache_eviction_maximum_page_size, cache->evict_max_page_size); - WT_STAT_SET(session, stats, cache_pages_dirty, cache->pages_dirty); - + WT_STAT_SET( + session, stats, cache_bytes_image, __wt_cache_bytes_image(cache)); + WT_STAT_SET( + session, stats, cache_pages_inuse, __wt_cache_pages_inuse(cache)); WT_STAT_SET( session, stats, cache_bytes_internal, cache->bytes_internal); + WT_STAT_SET(session, stats, cache_bytes_leaf, leaf); + WT_STAT_SET( + session, stats, cache_bytes_other, __wt_cache_bytes_other(cache)); WT_STAT_SET( session, stats, cache_bytes_overflow, cache->bytes_overflow); - WT_STAT_SET(session, stats, cache_bytes_leaf, leaf); + + WT_STAT_SET(session, stats, + cache_eviction_maximum_page_size, cache->evict_max_page_size); + WT_STAT_SET(session, stats, cache_pages_dirty, cache->pages_dirty); /* * The number of files with active walks ~= number of hazard pointers @@ -286,6 +294,7 @@ __wt_cache_destroy(WT_SESSION_IMPL *session) __wt_spin_destroy(session, &cache->evict_queues[i].evict_lock); __wt_free(session, cache->evict_queues[i].evict_queue); } + __wt_free(session, conn->cache); return (ret); } diff --git a/src/evict/evict_lru.c b/src/evict/evict_lru.c index 7eb35b6554e..4be1aab8181 100644 --- a/src/evict/evict_lru.c +++ b/src/evict/evict_lru.c @@ -529,6 +529,9 @@ __evict_update_work(WT_SESSION_IMPL *session) if (!F_ISSET(conn, WT_CONN_EVICTION_RUN)) return (false); + if (cache->evict_queues[WT_EVICT_URGENT_QUEUE].evict_current != NULL) + goto done; + /* * Setup the number of refs to consider in each handle, depending * on how many handles are open. We want to consider less candidates @@ -549,7 +552,7 @@ __evict_update_work(WT_SESSION_IMPL *session) bytes_max = conn->cache_size + 1; bytes_inuse = __wt_cache_bytes_inuse(cache); if (bytes_inuse > (cache->eviction_target * bytes_max) / 100) { - FLD_SET(cache->state, WT_EVICT_PASS_ALL); + FLD_SET(cache->state, WT_EVICT_STATE_ALL); goto done; } @@ -562,19 +565,7 @@ __evict_update_work(WT_SESSION_IMPL *session) dirty_inuse = __wt_cache_dirty_inuse(cache); if (dirty_inuse > (cache->eviction_dirty_target * bytes_max) / 100) { - FLD_SET(cache->state, WT_EVICT_PASS_DIRTY); - goto done; - } - - /* - * Evict pages with oldest generation (which would otherwise block - * application threads), set regardless of whether we have reached - * the eviction trigger. - */ - if (F_ISSET(cache, WT_CACHE_WOULD_BLOCK)) { - FLD_SET(cache->state, WT_EVICT_PASS_WOULD_BLOCK); - - F_CLR(cache, WT_CACHE_WOULD_BLOCK); + FLD_SET(cache->state, WT_EVICT_STATE_DIRTY); goto done; } @@ -583,7 +574,7 @@ __evict_update_work(WT_SESSION_IMPL *session) done: if (F_ISSET(cache, WT_CACHE_STUCK)) { WT_STAT_FAST_CONN_SET(session, cache_eviction_aggressive_set, 1); - FLD_SET(cache->state, WT_EVICT_PASS_AGGRESSIVE); + FLD_SET(cache->state, WT_EVICT_STATE_AGGRESSIVE); } return (true); } @@ -643,15 +634,15 @@ __evict_pass(WT_SESSION_IMPL *session) if (loop > 10) { WT_STAT_FAST_CONN_SET(session, cache_eviction_aggressive_set, 1); - FLD_SET(cache->state, WT_EVICT_PASS_AGGRESSIVE); + FLD_SET(cache->state, WT_EVICT_STATE_AGGRESSIVE); } /* * Start a worker if we have capacity and we haven't reached * the eviction targets. */ - if (FLD_ISSET(cache->state, WT_EVICT_PASS_ALL | - WT_EVICT_PASS_DIRTY | WT_EVICT_PASS_WOULD_BLOCK) && + if (FLD_ISSET(cache->state, + WT_EVICT_STATE_ALL | WT_EVICT_STATE_DIRTY) && conn->evict_workers < conn->evict_workers_max) { WT_RET(__wt_verbose(session, WT_VERB_EVICTSERVER, "Starting evict worker: %"PRIu32"\n", @@ -692,15 +683,12 @@ __evict_pass(WT_SESSION_IMPL *session) * Mark the cache as stuck if we need space * and aren't evicting any pages. */ - if (!FLD_ISSET(cache->state, - WT_EVICT_PASS_WOULD_BLOCK)) { - F_SET(cache, WT_CACHE_STUCK); - WT_STAT_FAST_CONN_INCR( - session, cache_eviction_slow); - WT_RET(__wt_verbose( - session, WT_VERB_EVICTSERVER, - "unable to reach eviction goal")); - } + F_SET(cache, WT_CACHE_STUCK); + WT_STAT_FAST_CONN_INCR( + session, cache_eviction_slow); + WT_RET(__wt_verbose( + session, WT_VERB_EVICTSERVER, + "unable to reach eviction goal")); break; } } else { @@ -923,27 +911,29 @@ __evict_lru_walk(WT_SESSION_IMPL *session) { WT_CACHE *cache; WT_DECL_RET; - WT_EVICT_QUEUE *evict_queue; + WT_EVICT_QUEUE *queue; uint64_t read_gen_oldest; uint32_t candidates, entries, queue_index; cache = S2C(session)->cache; - queue_index = cache->evict_queue_fill++ % WT_EVICT_QUEUE_MAX; - evict_queue = &cache->evict_queues[queue_index]; + /* 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]; /* Get some more pages to consider for eviction. */ if ((ret = __evict_walk(cache->walk_session, queue_index)) != 0) return (ret == EBUSY ? 0 : ret); /* Sort the list into LRU order and restart. */ - __wt_spin_lock(session, &evict_queue->evict_lock); + __wt_spin_lock(session, &queue->evict_lock); - entries = evict_queue->evict_entries; - qsort(evict_queue->evict_queue, + entries = queue->evict_entries; + qsort(queue->evict_queue, entries, sizeof(WT_EVICT_ENTRY), __evict_lru_cmp); - while (entries > 0 && evict_queue->evict_queue[entries - 1].ref == NULL) + while (entries > 0 && queue->evict_queue[entries - 1].ref == NULL) --entries; /* @@ -953,9 +943,9 @@ __evict_lru_walk(WT_SESSION_IMPL *session) */ while (entries > WT_EVICT_WALK_BASE) __evict_list_clear(session, - &evict_queue->evict_queue[--entries]); + &queue->evict_queue[--entries]); - evict_queue->evict_entries = entries; + queue->evict_entries = entries; if (entries == 0) { /* @@ -963,23 +953,19 @@ __evict_lru_walk(WT_SESSION_IMPL *session) * Make sure application threads don't read past the end of the * candidate list, or they may race with the next walk. */ - evict_queue->evict_candidates = 0; - __wt_spin_unlock(session, &evict_queue->evict_lock); - __wt_spin_lock(session, &cache->evict_queue_lock); - cache->evict_current = NULL; - cache->evict_current_queue = NULL; - __wt_spin_unlock(session, &cache->evict_queue_lock); + queue->evict_candidates = 0; + queue->evict_current = NULL; + __wt_spin_unlock(session, &queue->evict_lock); return (0); } /* Decide how many of the candidates we're going to try and evict. */ - if (FLD_ISSET(cache->state, - WT_EVICT_PASS_AGGRESSIVE | WT_EVICT_PASS_WOULD_BLOCK)) { + if (FLD_ISSET(cache->state, WT_EVICT_STATE_AGGRESSIVE)) { /* * Take all candidates if we only gathered pages with an oldest * read generation set. */ - evict_queue->evict_candidates = entries; + queue->evict_candidates = entries; } else { /* * Find the oldest read generation we have in the queue, used @@ -989,7 +975,7 @@ __evict_lru_walk(WT_SESSION_IMPL *session) read_gen_oldest = WT_READGEN_OLDEST; for (candidates = 0; candidates < entries; ++candidates) { read_gen_oldest = - evict_queue->evict_queue[candidates].score; + queue->evict_queue[candidates].score; if (read_gen_oldest != WT_READGEN_OLDEST) break; } @@ -1003,9 +989,9 @@ __evict_lru_walk(WT_SESSION_IMPL *session) * all of them. */ if (read_gen_oldest == WT_READGEN_OLDEST) - evict_queue->evict_candidates = entries; + queue->evict_candidates = entries; else if (candidates > entries / 2) - evict_queue->evict_candidates = candidates; + queue->evict_candidates = candidates; else { /* * Take all of the urgent pages plus a third of @@ -1018,24 +1004,25 @@ __evict_lru_walk(WT_SESSION_IMPL *session) * normal when populating an empty file, don't exclude * it. */ - evict_queue->evict_candidates = + queue->evict_candidates = 1 + candidates + ((entries - candidates) - 1) / 3; cache->read_gen_oldest = read_gen_oldest; } } - __wt_spin_unlock(session, &evict_queue->evict_lock); + 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 == NULL) + if (cache->evict_current_queue->evict_current == NULL) WT_STAT_FAST_CONN_INCR(session, cache_eviction_queue_empty); else WT_STAT_FAST_CONN_INCR(session, cache_eviction_queue_not_empty); - cache->evict_current = evict_queue->evict_queue; - cache->evict_current_queue = evict_queue; + cache->evict_current_queue = queue; __wt_spin_unlock(session, &cache->evict_queue_lock); /* @@ -1059,7 +1046,7 @@ __evict_walk(WT_SESSION_IMPL *session, uint32_t queue_index) WT_CONNECTION_IMPL *conn; WT_DATA_HANDLE *dhandle; WT_DECL_RET; - WT_EVICT_QUEUE *evict_queue; + WT_EVICT_QUEUE *queue; u_int max_entries, prev_slot, retries, slot, start_slot, spins; bool dhandle_locked, incr; @@ -1074,8 +1061,8 @@ __evict_walk(WT_SESSION_IMPL *session, uint32_t queue_index) * Set the starting slot in the queue and the maximum pages added * per walk. */ - evict_queue = &cache->evict_queues[queue_index]; - start_slot = slot = evict_queue->evict_entries; + queue = &cache->evict_queues[queue_index]; + start_slot = slot = queue->evict_entries; max_entries = WT_MIN(slot + WT_EVICT_WALK_INCR, cache->evict_slots); retry: while (slot < max_entries && ret == 0) { @@ -1146,7 +1133,7 @@ retry: while (slot < max_entries && ret == 0) { */ if ((btree->checkpointing != WT_CKPT_OFF || btree->evict_priority != 0) && - !FLD_ISSET(cache->state, WT_EVICT_PASS_AGGRESSIVE)) + !FLD_ISSET(cache->state, WT_EVICT_STATE_AGGRESSIVE)) continue; /* Skip files if we have used all available hazard pointers. */ @@ -1221,40 +1208,49 @@ retry: while (slot < max_entries && ret == 0) { if (cache->pass_intr == 0 && ret == 0 && slot < max_entries && (retries < 2 || (retries < 10 && - !FLD_ISSET(cache->state, WT_EVICT_PASS_WOULD_BLOCK) && - (slot == evict_queue->evict_entries || slot > start_slot)))) { + (slot == queue->evict_entries || slot > start_slot)))) { start_slot = slot; ++retries; goto retry; } - evict_queue->evict_entries = slot; + queue->evict_entries = slot; return (ret); } /* - * __evict_init_candidate -- + * __evict_push_candidate -- * Initialize a WT_EVICT_ENTRY structure with a given page. */ -static void -__evict_init_candidate(WT_SESSION_IMPL *session, - WT_EVICT_QUEUE *evict_queue, WT_EVICT_ENTRY *evict, WT_REF *ref) +static bool +__evict_push_candidate(WT_SESSION_IMPL *session, + WT_EVICT_QUEUE *queue, WT_EVICT_ENTRY *evict, WT_REF *ref) { u_int slot; + uint8_t orig_flags, new_flags; + + /* + * Threads can race to queue a page (e.g., an ordinary LRU walk can + * race with a page being queued for urgent eviction. + */ + orig_flags = new_flags = ref->page->flags_atomic; + FLD_SET(new_flags, WT_PAGE_EVICT_LRU); + if (orig_flags == new_flags || + !__wt_atomic_cas8(&ref->page->flags_atomic, orig_flags, new_flags)) + return (false); /* Keep track of the maximum slot we are using. */ - slot = (u_int)(evict - evict_queue->evict_queue); - if (slot >= evict_queue->evict_max) - evict_queue->evict_max = slot + 1; + slot = (u_int)(evict - queue->evict_queue); + if (slot >= queue->evict_max) + queue->evict_max = slot + 1; if (evict->ref != NULL) __evict_list_clear(session, evict); + evict->btree = S2BT(session); evict->ref = ref; evict->score = __evict_read_gen(evict); - - /* Mark the page on the list; set last to flush the other updates. */ - F_SET_ATOMIC(ref->page, WT_PAGE_EVICT_LRU); + return (true); } /* @@ -1270,7 +1266,7 @@ __evict_walk_file(WT_SESSION_IMPL *session, WT_CONNECTION_IMPL *conn; WT_DECL_RET; WT_EVICT_ENTRY *end, *evict, *start; - WT_EVICT_QUEUE *evict_queue; + WT_EVICT_QUEUE *queue; WT_PAGE *page; WT_PAGE_MODIFY *mod; WT_REF *ref; @@ -1283,7 +1279,7 @@ __evict_walk_file(WT_SESSION_IMPL *session, conn = S2C(session); btree = S2BT(session); cache = conn->cache; - evict_queue = &cache->evict_queues[queue_index]; + queue = &cache->evict_queues[queue_index]; internal_pages = restarts = 0; enough = false; @@ -1291,11 +1287,11 @@ __evict_walk_file(WT_SESSION_IMPL *session, * Figure out how many slots to fill from this tree. * Note that some care is taken in the calculation to avoid overflow. */ - start = evict_queue->evict_queue + *slotp; + start = queue->evict_queue + *slotp; remaining_slots = max_entries - *slotp; btree_inuse = __wt_btree_bytes_inuse(session); cache_inuse = __wt_cache_bytes_inuse(cache); - total_slots = max_entries - evict_queue->evict_entries; + total_slots = max_entries - queue->evict_entries; /* * The target number of pages for this tree is proportional to the @@ -1395,25 +1391,17 @@ __evict_walk_file(WT_SESSION_IMPL *session, goto fast; } if (__wt_page_is_empty(page) || - F_ISSET(session->dhandle, WT_DHANDLE_DEAD)) + F_ISSET(session->dhandle, WT_DHANDLE_DEAD) || + FLD_ISSET(cache->state, WT_EVICT_STATE_AGGRESSIVE)) goto fast; /* Skip clean pages if appropriate. */ if (!modified && (F_ISSET(conn, WT_CONN_IN_MEMORY) || - FLD_ISSET(cache->state, WT_EVICT_PASS_DIRTY))) - continue; - - /* - * If we are only trickling out pages marked for definite - * eviction, skip anything that isn't marked. - */ - if (FLD_ISSET(cache->state, WT_EVICT_PASS_WOULD_BLOCK) && - page->memory_footprint < btree->splitmempage) + FLD_ISSET(cache->state, WT_EVICT_STATE_DIRTY))) continue; - /* Limit internal pages to 50% unless we get aggressive. */ + /* Limit internal pages to 50% of the total. */ if (WT_PAGE_IS_INTERNAL(page) && - !FLD_ISSET(cache->state, WT_EVICT_PASS_AGGRESSIVE) && internal_pages >= (int)(evict - start) / 2) continue; @@ -1437,8 +1425,7 @@ fast: /* If the page can't be evicted, give up. */ * configure lookaside table writes in reconciliation, allowing * us to evict pages we can't usually evict. */ - if (!FLD_ISSET(cache->state, - WT_EVICT_PASS_AGGRESSIVE | WT_EVICT_PASS_WOULD_BLOCK)) { + if (!FLD_ISSET(cache->state, WT_EVICT_STATE_AGGRESSIVE)) { /* * If the page is clean but has modifications that * appear too new to evict, skip it. @@ -1449,7 +1436,8 @@ fast: /* If the page can't be evicted, give up. */ } WT_ASSERT(session, evict->ref == NULL); - __evict_init_candidate(session, evict_queue, evict, ref); + if (!__evict_push_candidate(session, queue, evict, ref)) + continue; ++evict; if (WT_PAGE_IS_INTERNAL(page)) @@ -1506,19 +1494,21 @@ __evict_check_entry_size(WT_SESSION_IMPL *session, WT_EVICT_ENTRY *entry) cache = S2C(session)->cache; - if (cache->pages_evict == 0) + if (cache->pages_evict == 0 || cache->bytes_evict < WT_MEGABYTE) return (true); max = (cache->bytes_evict / cache->pages_evict) * 4; if ((ref = entry->ref) != NULL) { if ((page = ref->page) == NULL) return (true); + /* - * If this page is more than four times the average evicted page - * size then return false. Return true in all other cases. - * XXX Should we care here if the page is dirty? Probably... + * If this page is dirty and more than four times the average + * evicted page size then return false. Return true in all + * other cases. */ - if (page->memory_footprint > max) { + if (__wt_page_is_modified(page) && + page->memory_footprint > max) { WT_STAT_FAST_CONN_INCR( session, cache_eviction_server_toobig); return (false); @@ -1537,72 +1527,82 @@ __evict_get_ref( { WT_CACHE *cache; WT_EVICT_ENTRY *evict; - WT_EVICT_QUEUE *evict_queue; + WT_EVICT_QUEUE *queue, *urgent_queue; uint32_t candidates; cache = S2C(session)->cache; + urgent_queue = &cache->evict_queues[WT_EVICT_URGENT_QUEUE]; *btreep = NULL; *refp = NULL; - /* - * Avoid the LRU lock if no pages are available. - */ + /* Avoid the LRU lock if no pages are available. */ WT_STAT_FAST_CONN_INCR(session, cache_eviction_get_ref); - if (cache->evict_current == NULL) { + if (cache->evict_current_queue->evict_current == NULL && + urgent_queue->evict_current == NULL) { WT_STAT_FAST_CONN_INCR(session, cache_eviction_get_ref_empty); return (WT_NOTFOUND); } __wt_spin_lock(session, &cache->evict_queue_lock); + + /* 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 || S2C(session)->evict_workers <= 1))) ? + urgent_queue : cache->evict_current_queue; + + __wt_spin_unlock(session, &cache->evict_queue_lock); + /* - * Verify there are still pages available. + * Only evict half of the pages before looking for more. The remainder + * are left to eviction workers (if configured), or application threads + * if necessary. */ - if (cache->evict_current == NULL) { - __wt_spin_unlock(session, &cache->evict_queue_lock); - WT_STAT_FAST_CONN_INCR(session, cache_eviction_get_ref_empty2); - return (WT_NOTFOUND); - } + candidates = queue->evict_candidates; + if (is_server && queue != urgent_queue && candidates > 1) + candidates /= 2; /* - * We got the queue lock, which should be fast, and now we want to - * get the lock on the individual queue. We know that the shared - * queue fields cannot change now. + * We got the queue lock, which should be fast, and chose a queue. + * Now we want to get the lock on the individual queue. */ - evict_queue = cache->evict_current_queue; for (;;) { - if (__wt_spin_trylock(session, &evict_queue->evict_lock) == 0) - break; - if (!F_ISSET(session, WT_SESSION_INTERNAL)) { - __wt_spin_unlock(session, &cache->evict_queue_lock); + /* Verify there are still pages available. */ + if (queue->evict_current == NULL || + (queue->evict_current - queue->evict_queue) >= candidates) { + WT_STAT_FAST_CONN_INCR( + session, cache_eviction_get_ref_empty2); return (WT_NOTFOUND); } - __wt_yield(); + if (!is_server) + __wt_spin_lock(session, &queue->evict_lock); + else if (__wt_spin_trylock( + session, &queue->evict_lock) != 0) + continue; + break; } - /* - * Only evict half of the pages before looking for more. The remainder - * are left to eviction workers (if configured), or application threads - * if necessary. - */ - candidates = evict_queue->evict_candidates; - if (is_server && candidates > 1) - candidates /= 2; - /* Get the next page queued for eviction. */ - for (evict = cache->evict_current; - evict >= evict_queue->evict_queue && - evict < evict_queue->evict_queue + candidates; + for (evict = queue->evict_current; + evict >= queue->evict_queue && + evict < queue->evict_queue + candidates; ++evict) { if (evict->ref == NULL) continue; WT_ASSERT(session, evict->btree != NULL); + /* - * If the server is helping out and encounters an entry that - * is too large, it stops helping. Evicting a very large - * page in the server thread could stall eviction from finding - * new work. + * If the server is helping out and encounters an entry that is + * too large, it stops helping. Evicting a very large page in + * the server thread could stall eviction from finding new + * work. + * + * However, we can't skip entries in the urgent queue or they + * may never be found again. */ - if (is_server && S2C(session)->evict_workers > 1 && + if (is_server && queue != urgent_queue && + S2C(session)->evict_workers > 1 && !__evict_check_entry_size(session, evict)) continue; @@ -1634,14 +1634,14 @@ __evict_get_ref( break; } - /* Clear the current pointer if there are no more candidates. */ - if (evict == NULL || evict + 1 >= - evict_queue->evict_queue + evict_queue->evict_candidates) - cache->evict_current = NULL; - else - cache->evict_current = evict + 1; - __wt_spin_unlock(session, &evict_queue->evict_lock); - __wt_spin_unlock(session, &cache->evict_queue_lock); + /* Move to the next item. */ + if (evict != NULL && evict + 1 < + queue->evict_queue + queue->evict_candidates) + queue->evict_current = evict + 1; + else /* Clear the current pointer if there are no more candidates. */ + queue->evict_current = NULL; + + __wt_spin_unlock(session, &queue->evict_lock); return ((*refp == NULL) ? WT_NOTFOUND : 0); } @@ -1799,6 +1799,59 @@ __wt_cache_eviction_worker(WT_SESSION_IMPL *session, bool busy, u_int pct_full) } /* + * __wt_page_evict_soon -- + * Set a page to be evicted as soon as possible. + */ +int +__wt_page_evict_soon(WT_SESSION_IMPL *session, WT_REF *ref) +{ + WT_CACHE *cache; + WT_EVICT_ENTRY *evict; + WT_EVICT_QUEUE *urgent_queue; + WT_PAGE *page; + bool queued; + + 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 (0); + + /* Append to the urgent queue if we can. */ + cache = S2C(session)->cache; + urgent_queue = &cache->evict_queues[WT_EVICT_URGENT_QUEUE]; + queued = false; + + __wt_spin_lock(session, &cache->evict_queue_lock); + if (F_ISSET_ATOMIC(page, WT_PAGE_EVICT_LRU) || + F_ISSET(S2BT(session), WT_BTREE_NO_EVICTION)) + goto done; + + __wt_spin_lock(session, &urgent_queue->evict_lock); + if (urgent_queue->evict_current == NULL) { + 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 && + __evict_push_candidate(session, urgent_queue, evict, ref)) { + ++urgent_queue->evict_candidates; + queued = true; + } + __wt_spin_unlock(session, &urgent_queue->evict_lock); + +done: __wt_spin_unlock(session, &cache->evict_queue_lock); + if (queued) { + if (S2C(session)->evict_workers > 1) + WT_RET(__wt_cond_signal( + session, cache->evict_waiter_cond)); + else + WT_RET(__wt_evict_server_wake(session)); + } + return (0); +} + +/* * __wt_evict_priority_set -- * Set a tree's eviction priority. */ diff --git a/src/evict/evict_page.c b/src/evict/evict_page.c index 305b81fe69e..f5c900684a3 100644 --- a/src/evict/evict_page.c +++ b/src/evict/evict_page.c @@ -10,7 +10,7 @@ static int __evict_page_clean_update(WT_SESSION_IMPL *, WT_REF *, bool); static int __evict_page_dirty_update(WT_SESSION_IMPL *, WT_REF *, bool); -static int __evict_review(WT_SESSION_IMPL *, WT_REF *, bool *, bool); +static int __evict_review(WT_SESSION_IMPL *, WT_REF *, uint32_t *, bool); /* * __evict_exclusive_clear -- @@ -46,6 +46,55 @@ __evict_exclusive(WT_SESSION_IMPL *session, WT_REF *ref) } /* + * __wt_page_release_evict -- + * Release a reference to a page, and attempt to immediately evict it. + */ +int +__wt_page_release_evict(WT_SESSION_IMPL *session, WT_REF *ref) +{ + WT_BTREE *btree; + WT_DECL_RET; + WT_PAGE *page; + bool locked, too_big; + + btree = S2BT(session); + page = ref->page; + + /* + * Take some care with order of operations: if we release the hazard + * reference without first locking the page, it could be evicted in + * between. + */ + locked = __wt_atomic_casv32(&ref->state, WT_REF_MEM, WT_REF_LOCKED); + if ((ret = __wt_hazard_clear(session, page)) != 0 || !locked) { + if (locked) + ref->state = WT_REF_MEM; + return (ret == 0 ? EBUSY : ret); + } + + (void)__wt_atomic_addv32(&btree->evict_busy, 1); + + 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); + else + /* + * If the page isn't too big, we are evicting it because + * it had a chain of deleted entries that make traversal + * expensive. + */ + WT_STAT_FAST_CONN_INCR( + session, cache_eviction_force_delete); + } else + WT_STAT_FAST_CONN_INCR(session, cache_eviction_force_fail); + + (void)__wt_atomic_subv32(&btree->evict_busy, 1); + + return (ret); +} + +/* * __wt_evict -- * Evict a page. */ @@ -56,7 +105,8 @@ __wt_evict(WT_SESSION_IMPL *session, WT_REF *ref, bool closing) WT_DECL_RET; WT_PAGE *page; WT_PAGE_MODIFY *mod; - bool clean_page, forced_eviction, inmem_split, tree_dead; + uint32_t flags; + bool clean_page, tree_dead; conn = S2C(session); @@ -64,8 +114,6 @@ __wt_evict(WT_SESSION_IMPL *session, WT_REF *ref, bool closing) WT_ASSERT(session, !WT_SESSION_IS_CHECKPOINT(session)); page = ref->page; - forced_eviction = page->read_gen == WT_READGEN_OLDEST; - inmem_split = false; tree_dead = F_ISSET(session->dhandle, WT_DHANDLE_DEAD); WT_RET(__wt_verbose(session, WT_VERB_EVICT, @@ -78,14 +126,14 @@ __wt_evict(WT_SESSION_IMPL *session, WT_REF *ref, bool closing) * to make this check for clean pages, too: while unlikely eviction * would choose an internal page with children, it's not disallowed. */ - WT_ERR(__evict_review(session, ref, &inmem_split, closing)); + WT_ERR(__evict_review(session, ref, &flags, closing)); /* * If there was an in-memory split, the tree has been left in the state * we want: there is nothing more to do. */ - if (inmem_split) - goto done; + if (LF_ISSET(WT_EVICT_INMEM_SPLIT)) + return (0); /* * Update the page's modification reference, reconciliation might have @@ -113,7 +161,7 @@ __wt_evict(WT_SESSION_IMPL *session, WT_REF *ref, bool closing) /* Update the reference and discard the page. */ if (__wt_ref_is_root(ref)) __wt_ref_out(session, ref); - else if (tree_dead || (clean_page && !F_ISSET(conn, WT_CONN_IN_MEMORY))) + else if (tree_dead || (clean_page && !LF_ISSET(WT_EVICT_IN_MEMORY))) /* * Pages that belong to dead trees never write back to disk * and can't support page splits. @@ -139,14 +187,9 @@ err: if (!closing) WT_STAT_FAST_DATA_INCR(session, cache_eviction_fail); } -done: if (((inmem_split && ret == 0) || (forced_eviction && ret == EBUSY)) && - !F_ISSET(conn->cache, WT_CACHE_WOULD_BLOCK)) { - F_SET(conn->cache, WT_CACHE_WOULD_BLOCK); - WT_TRET(__wt_evict_server_wake(session)); - } - return (ret); } + /* * __evict_delete_ref -- * Mark a page reference deleted and check if the parent can reverse @@ -210,13 +253,6 @@ __evict_page_clean_update(WT_SESSION_IMPL *session, WT_REF *ref, bool closing) WT_DECL_RET; /* - * If doing normal system eviction, but only in the service of reducing - * the number of dirty pages, leave the clean page in cache. - */ - if (!closing && __wt_eviction_dirty_target(session)) - return (EBUSY); - - /* * Discard the page and update the reference structure; if the page has * an address, it's a disk page; if it has no address, it's a deleted * page re-instantiated (for example, by searching) and never written. @@ -291,17 +327,6 @@ __evict_page_dirty_update(WT_SESSION_IMPL *session, WT_REF *ref, bool closing) break; case WT_PM_REC_REPLACE: /* 1-for-1 page swap */ /* - * If doing normal system eviction, but only in the service of - * reducing the number of dirty pages, leave the clean page in - * cache. Only do this when replacing a page with another one, - * because when a page splits into multiple pages, we want to - * push it out of cache (and read it back in, when needed), we - * would rather have more, smaller pages than fewer large pages. - */ - if (!closing && __wt_eviction_dirty_target(session)) - return (EBUSY); - - /* * Update the parent to reference the replacement page. * * Publish: a barrier to ensure the structure fields are set @@ -351,13 +376,19 @@ __evict_child_check(WT_SESSION_IMPL *session, WT_REF *parent) */ static int __evict_review( - WT_SESSION_IMPL *session, WT_REF *ref, bool *inmem_splitp, bool closing) + WT_SESSION_IMPL *session, WT_REF *ref, uint32_t *flagsp, bool closing) { + WT_CACHE *cache; WT_DECL_RET; WT_PAGE *page; uint32_t flags; bool modified; + flags = WT_EVICTING; + if (closing) + LF_SET(WT_VISIBILITY_ERR); + *flagsp = flags; + /* * Get exclusive access to the page if our caller doesn't have the tree * locked down. @@ -423,8 +454,9 @@ __evict_review( WT_RET(__wt_txn_update_oldest( session, WT_TXN_OLDEST_STRICT)); - if (!__wt_page_can_evict(session, ref, inmem_splitp)) + if (!__wt_page_can_evict(session, ref, flagsp)) return (EBUSY); + flags = *flagsp; /* * Check for an append-only workload needing an in-memory @@ -433,7 +465,7 @@ __evict_review( * the page stays in memory and the tree is left in the desired * state: avoid the usual cleanup. */ - if (*inmem_splitp) + if (LF_ISSET(WT_EVICT_INMEM_SPLIT)) return (__wt_split_insert(session, ref)); } @@ -464,17 +496,17 @@ __evict_review( * Don't set the update-restore or lookaside table flags for internal * pages, they don't have update lists that can be saved and restored. */ - flags = WT_EVICTING; - if (closing) - LF_SET(WT_VISIBILITY_ERR); - else if (!WT_PAGE_IS_INTERNAL(page)) { + cache = S2C(session)->cache; + if (!closing && !WT_PAGE_IS_INTERNAL(page)) { if (F_ISSET(S2C(session), WT_CONN_IN_MEMORY)) LF_SET(WT_EVICT_IN_MEMORY | WT_EVICT_UPDATE_RESTORE); - else if (page->read_gen == WT_READGEN_OLDEST) + else if (page->read_gen == WT_READGEN_OLDEST || + page->memory_footprint > S2BT(session)->splitmempage) LF_SET(WT_EVICT_UPDATE_RESTORE); - else if (F_ISSET(S2C(session)->cache, WT_CACHE_STUCK)) + else if (F_ISSET(cache, WT_CACHE_STUCK)) LF_SET(WT_EVICT_LOOKASIDE); } + *flagsp = flags; WT_RET(__wt_reconcile(session, ref, NULL, flags)); diff --git a/src/include/btree.i b/src/include/btree.i index 84f2eff1b1b..c7950b4ea26 100644 --- a/src/include/btree.i +++ b/src/include/btree.i @@ -285,6 +285,34 @@ __wt_cache_dirty_decr(WT_SESSION_IMPL *session, WT_PAGE *page) } /* + * __wt_cache_page_image_decr -- + * Decrement a page image's size to the cache. + */ +static inline void +__wt_cache_page_image_decr(WT_SESSION_IMPL *session, uint32_t size) +{ + WT_CACHE *cache; + + cache = S2C(session)->cache; + + __wt_cache_decr_check_uint64( + session, &cache->bytes_image, size, "WT_CACHE.image_inmem"); +} + +/* + * __wt_cache_page_image_incr -- + * Increment a page image's size to the cache. + */ +static inline void +__wt_cache_page_image_incr(WT_SESSION_IMPL *session, uint32_t size) +{ + WT_CACHE *cache; + + cache = S2C(session)->cache; + (void)__wt_atomic_add64(&cache->bytes_image, size); +} + +/* * __wt_cache_page_evict -- * Evict pages from the cache. */ @@ -343,16 +371,6 @@ __wt_update_list_memsize(WT_UPDATE *upd) } /* - * __wt_page_evict_soon -- - * Set a page to be evicted as soon as possible. - */ -static inline void -__wt_page_evict_soon(WT_PAGE *page) -{ - page->read_gen = WT_READGEN_OLDEST; -} - -/* * __wt_page_modify_init -- * A page is about to be modified, allocate the modification structure. */ @@ -1124,23 +1142,27 @@ __wt_leaf_page_can_split(WT_SESSION_IMPL *session, WT_PAGE *page) * Check whether a page can be evicted. */ static inline bool -__wt_page_can_evict(WT_SESSION_IMPL *session, WT_REF *ref, bool *inmem_splitp) +__wt_page_can_evict( + WT_SESSION_IMPL *session, WT_REF *ref, uint32_t *evict_flagsp) { WT_BTREE *btree; WT_PAGE *page; WT_PAGE_MODIFY *mod; bool modified; - if (inmem_splitp != NULL) - *inmem_splitp = false; + if (evict_flagsp != NULL) + *evict_flagsp = WT_EVICTING; btree = S2BT(session); page = ref->page; mod = page->modify; /* Pages that have never been modified can always be evicted. */ - if (mod == NULL) + if (mod == NULL) { + if (evict_flagsp != NULL) + FLD_SET(*evict_flagsp, WT_EVICT_CLEAN); return (true); + } /* * Check for in-memory splits before other eviction tests. If the page @@ -1149,8 +1171,8 @@ __wt_page_can_evict(WT_SESSION_IMPL *session, WT_REF *ref, bool *inmem_splitp) * won't be written or discarded from the cache. */ if (__wt_leaf_page_can_split(session, page)) { - if (inmem_splitp != NULL) - *inmem_splitp = true; + if (evict_flagsp != NULL) + FLD_SET(*evict_flagsp, WT_EVICT_INMEM_SPLIT); return (true); } @@ -1189,6 +1211,10 @@ __wt_page_can_evict(WT_SESSION_IMPL *session, WT_REF *ref, bool *inmem_splitp) F_ISSET_ATOMIC(page, WT_PAGE_SPLIT_BLOCK)) return (false); + /* If the cache is stuck, try anything else. */ + if (F_ISSET(S2C(session)->cache, WT_CACHE_STUCK)) + return (true); + /* * If the oldest transaction hasn't changed since the last time * this page was written, it's unlikely we can make progress. @@ -1197,7 +1223,6 @@ __wt_page_can_evict(WT_SESSION_IMPL *session, WT_REF *ref, bool *inmem_splitp) * attempt to avoid repeated attempts to evict the same page. */ if (modified && - !F_ISSET(S2C(session)->cache, WT_CACHE_STUCK) && (mod->last_oldest_id == __wt_txn_oldest_id(session) || !__wt_txn_visible_all(session, mod->update_txn))) return (false); @@ -1206,56 +1231,6 @@ __wt_page_can_evict(WT_SESSION_IMPL *session, WT_REF *ref, bool *inmem_splitp) } /* - * __wt_page_release_evict -- - * Release a reference to a page, and attempt to immediately evict it. - */ -static inline int -__wt_page_release_evict(WT_SESSION_IMPL *session, WT_REF *ref) -{ - WT_BTREE *btree; - WT_DECL_RET; - WT_PAGE *page; - bool locked, too_big; - - btree = S2BT(session); - page = ref->page; - - /* - * Take some care with order of operations: if we release the hazard - * reference without first locking the page, it could be evicted in - * between. - */ - locked = __wt_atomic_casv32( - &ref->state, WT_REF_MEM, WT_REF_LOCKED) ? true : false; - if ((ret = __wt_hazard_clear(session, page)) != 0 || !locked) { - if (locked) - ref->state = WT_REF_MEM; - return (ret == 0 ? EBUSY : ret); - } - - (void)__wt_atomic_addv32(&btree->evict_busy, 1); - - too_big = page->memory_footprint > btree->maxmempage; - if ((ret = __wt_evict(session, ref, false)) == 0) { - if (too_big) - WT_STAT_FAST_CONN_INCR(session, cache_eviction_force); - else - /* - * If the page isn't too big, we are evicting it because - * it had a chain of deleted entries that make traversal - * expensive. - */ - WT_STAT_FAST_CONN_INCR( - session, cache_eviction_force_delete); - } else - WT_STAT_FAST_CONN_INCR(session, cache_eviction_force_fail); - - (void)__wt_atomic_subv32(&btree->evict_busy, 1); - - return (ret); -} - -/* * __wt_page_release -- * Release a reference to a page. */ diff --git a/src/include/cache.h b/src/include/cache.h index bfbb65878f8..dbc4074330a 100644 --- a/src/include/cache.h +++ b/src/include/cache.h @@ -26,7 +26,9 @@ struct __wt_evict_entry { uint64_t score; /* Relative eviction priority */ }; -#define WT_EVICT_QUEUE_MAX 2 +#define WT_EVICT_URGENT_QUEUE 0 /* Urgent queue index */ +#define WT_EVICT_QUEUE_MAX 3 /* Urgent plus two ordinary queues */ + /* * WT_EVICT_QUEUE -- * Encapsulation of an eviction candidate queue. @@ -34,6 +36,7 @@ struct __wt_evict_entry { struct __wt_evict_queue { WT_SPINLOCK evict_lock; /* Eviction LRU queue */ WT_EVICT_ENTRY *evict_queue; /* LRU pages being tracked */ + WT_EVICT_ENTRY *evict_current; /* LRU current page to be evicted */ uint32_t evict_candidates; /* LRU list pages to evict */ uint32_t evict_entries; /* LRU entries in the queue */ volatile uint32_t evict_max; /* LRU maximum eviction slot used */ @@ -70,15 +73,16 @@ struct __wt_cache { * be exact, they can't be garbage, we track what comes in and what goes * out and calculate the difference as needed. */ + uint64_t bytes_dirty; /* Bytes/pages currently dirty */ + uint64_t pages_dirty; + uint64_t bytes_evict; /* Bytes/pages discarded by eviction */ + uint64_t pages_evict; + uint64_t pages_evicted; /* Pages evicted during a pass */ + uint64_t bytes_image; /* Bytes of disk images */ uint64_t bytes_inmem; /* Bytes/pages in memory */ uint64_t pages_inmem; uint64_t bytes_internal; /* Bytes of internal pages */ uint64_t bytes_overflow; /* Bytes of overflow pages */ - uint64_t bytes_evict; /* Bytes/pages discarded by eviction */ - uint64_t pages_evict; - uint64_t pages_evicted; /* Pages evicted during a pass */ - uint64_t bytes_dirty; /* Bytes/pages currently dirty */ - uint64_t pages_dirty; uint64_t bytes_read; /* Bytes read into memory */ uint64_t app_waits; /* User threads waited for cache */ @@ -121,7 +125,6 @@ struct __wt_cache { 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 */ - WT_EVICT_ENTRY *evict_current; /* LRU current page to be evicted */ uint32_t evict_queue_fill; /* LRU eviction queue index to fill */ uint32_t evict_slots; /* LRU list eviction slots */ WT_DATA_HANDLE @@ -145,10 +148,9 @@ struct __wt_cache { /* * Work state. */ -#define WT_EVICT_PASS_AGGRESSIVE 0x01 -#define WT_EVICT_PASS_ALL 0x02 -#define WT_EVICT_PASS_DIRTY 0x04 -#define WT_EVICT_PASS_WOULD_BLOCK 0x08 +#define WT_EVICT_STATE_AGGRESSIVE 0x01 +#define WT_EVICT_STATE_ALL 0x02 +#define WT_EVICT_STATE_DIRTY 0x04 uint32_t state; /* * Pass interrupt counter. @@ -162,7 +164,6 @@ struct __wt_cache { #define WT_CACHE_POOL_RUN 0x02 /* Cache pool thread running */ #define WT_CACHE_STUCK 0x04 /* Eviction server is stuck */ #define WT_CACHE_WALK_REVERSE 0x08 /* Scan backwards for candidates */ -#define WT_CACHE_WOULD_BLOCK 0x10 /* Pages that would block apps */ uint32_t flags; }; diff --git a/src/include/cache.i b/src/include/cache.i index 72c8307756d..105dfd7202f 100644 --- a/src/include/cache.i +++ b/src/include/cache.i @@ -113,6 +113,50 @@ __wt_cache_dirty_inuse(WT_CACHE *cache) } /* + * __wt_cache_bytes_image -- + * Return the number of page image bytes in use. + */ +static inline uint64_t +__wt_cache_bytes_image(WT_CACHE *cache) +{ + uint64_t bytes_image; + + bytes_image = cache->bytes_image; + if (cache->overhead_pct != 0) + bytes_image += + (bytes_image * (uint64_t)cache->overhead_pct) / 100; + + return (bytes_image); +} + +/* + * __wt_cache_bytes_other -- + * Return the number of bytes in use not for page images. + */ +static inline uint64_t +__wt_cache_bytes_other(WT_CACHE *cache) +{ + uint64_t bytes_image, bytes_inmem, bytes_other; + + bytes_image = cache->bytes_image; + bytes_inmem = cache->bytes_inmem; + + /* + * The reads above could race with changes to the values, so protect + * against underflow. + */ + if (bytes_image > bytes_inmem) + return (0); + + bytes_other = bytes_inmem - bytes_image; + if (cache->overhead_pct != 0) + bytes_other += + (bytes_other * (uint64_t)cache->overhead_pct) / 100; + + return (bytes_other); +} + +/* * __wt_session_can_wait -- * Return if a session available for a potentially slow operation. */ @@ -139,17 +183,6 @@ __wt_session_can_wait(WT_SESSION_IMPL *session) } /* - * __wt_eviction_dirty_target -- - * Return if the eviction server is running to reduce the number of dirty - * pages (versus running to discard pages from the cache). - */ -static inline bool -__wt_eviction_dirty_target(WT_SESSION_IMPL *session) -{ - return (FLD_ISSET(S2C(session)->cache->state, WT_EVICT_PASS_DIRTY)); -} - -/* * __wt_eviction_needed -- * Return if an application thread should do eviction, and the cache full * percentage as a side-effect. @@ -186,14 +219,6 @@ __wt_eviction_needed(WT_SESSION_IMPL *session, u_int *pct_fullp) pct_full = (u_int)((100 * bytes_inuse) / bytes_max); if (pct_fullp != NULL) *pct_fullp = pct_full; - /* - * If the connection is closing we do not need eviction from an - * application thread. The eviction subsystem is already closed. - * We return here because some callers depend on the percent full - * having been filled in. - */ - if (F_ISSET(conn, WT_CONN_CLOSING)) - return (false); if (pct_full > cache->eviction_trigger) return (true); diff --git a/src/include/cursor.i b/src/include/cursor.i index 553dd03f958..c7b6fdd88bc 100644 --- a/src/include/cursor.i +++ b/src/include/cursor.i @@ -120,7 +120,7 @@ __curfile_leave(WT_CURSOR_BTREE *cbt) */ if (cbt->ref != NULL && cbt->page_deleted_count > WT_BTREE_DELETE_THRESHOLD) - __wt_page_evict_soon(cbt->ref->page); + __wt_page_evict_soon(session, cbt->ref); cbt->page_deleted_count = 0; /* diff --git a/src/include/extern.h b/src/include/extern.h index b0c0f6eccad..2340f1d66a0 100644 --- a/src/include/extern.h +++ b/src/include/extern.h @@ -346,9 +346,11 @@ extern int __wt_evict_destroy(WT_SESSION_IMPL *session); extern int __wt_evict_file_exclusive_on(WT_SESSION_IMPL *session); 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); +extern int __wt_page_evict_soon(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); +extern int __wt_page_release_evict(WT_SESSION_IMPL *session, WT_REF *ref); extern int __wt_evict(WT_SESSION_IMPL *session, WT_REF *ref, bool closing); extern int __wt_log_ckpt(WT_SESSION_IMPL *session, WT_LSN *ckp_lsn); extern int __wt_log_flush_lsn(WT_SESSION_IMPL *session, WT_LSN *lsn, bool start); diff --git a/src/include/flags.h b/src/include/flags.h index f134af69d29..2145174ca6f 100644 --- a/src/include/flags.h +++ b/src/include/flags.h @@ -22,9 +22,11 @@ #define WT_CONN_SERVER_SWEEP 0x00020000 #define WT_CONN_WAS_BACKUP 0x00040000 #define WT_EVICTING 0x00000001 -#define WT_EVICT_IN_MEMORY 0x00000002 -#define WT_EVICT_LOOKASIDE 0x00000004 -#define WT_EVICT_UPDATE_RESTORE 0x00000008 +#define WT_EVICT_CLEAN 0x00000002 +#define WT_EVICT_INMEM_SPLIT 0x00000004 +#define WT_EVICT_IN_MEMORY 0x00000008 +#define WT_EVICT_LOOKASIDE 0x00000010 +#define WT_EVICT_UPDATE_RESTORE 0x00000020 #define WT_LOGSCAN_FIRST 0x00000001 #define WT_LOGSCAN_FROM_CKP 0x00000002 #define WT_LOGSCAN_ONE 0x00000004 @@ -100,7 +102,7 @@ #define WT_VERB_VERIFY 0x00800000 #define WT_VERB_VERSION 0x01000000 #define WT_VERB_WRITE 0x02000000 -#define WT_VISIBILITY_ERR 0x00000010 +#define WT_VISIBILITY_ERR 0x00000040 /* * flags section: END * DO NOT EDIT: automatically built by dist/flags.py. diff --git a/src/include/stat.h b/src/include/stat.h index 054d154f053..f64e3ce57a4 100644 --- a/src/include/stat.h +++ b/src/include/stat.h @@ -275,7 +275,9 @@ struct __wt_connection_stats { int64_t block_byte_write; int64_t block_map_read; int64_t block_byte_map_read; + int64_t cache_bytes_image; int64_t cache_bytes_inuse; + int64_t cache_bytes_other; int64_t cache_bytes_read; int64_t cache_bytes_write; int64_t cache_eviction_checkpoint; diff --git a/src/include/wiredtiger.in b/src/include/wiredtiger.in index 859b76d1367..4903185625a 100644 --- a/src/include/wiredtiger.in +++ b/src/include/wiredtiger.in @@ -4260,336 +4260,340 @@ extern int wiredtiger_extension_terminate(WT_CONNECTION *connection); #define WT_STAT_CONN_BLOCK_MAP_READ 1028 /*! block-manager: mapped bytes read */ #define WT_STAT_CONN_BLOCK_BYTE_MAP_READ 1029 +/*! cache: bytes belonging to page images in the cache */ +#define WT_STAT_CONN_CACHE_BYTES_IMAGE 1030 /*! cache: bytes currently in the cache */ -#define WT_STAT_CONN_CACHE_BYTES_INUSE 1030 +#define WT_STAT_CONN_CACHE_BYTES_INUSE 1031 +/*! cache: bytes not belonging to page images in the cache */ +#define WT_STAT_CONN_CACHE_BYTES_OTHER 1032 /*! cache: bytes read into cache */ -#define WT_STAT_CONN_CACHE_BYTES_READ 1031 +#define WT_STAT_CONN_CACHE_BYTES_READ 1033 /*! cache: bytes written from cache */ -#define WT_STAT_CONN_CACHE_BYTES_WRITE 1032 +#define WT_STAT_CONN_CACHE_BYTES_WRITE 1034 /*! cache: checkpoint blocked page eviction */ -#define WT_STAT_CONN_CACHE_EVICTION_CHECKPOINT 1033 +#define WT_STAT_CONN_CACHE_EVICTION_CHECKPOINT 1035 /*! cache: eviction calls to get a page */ -#define WT_STAT_CONN_CACHE_EVICTION_GET_REF 1034 +#define WT_STAT_CONN_CACHE_EVICTION_GET_REF 1036 /*! cache: eviction calls to get a page found queue empty */ -#define WT_STAT_CONN_CACHE_EVICTION_GET_REF_EMPTY 1035 +#define WT_STAT_CONN_CACHE_EVICTION_GET_REF_EMPTY 1037 /*! cache: eviction calls to get a page found queue empty after locking */ -#define WT_STAT_CONN_CACHE_EVICTION_GET_REF_EMPTY2 1036 +#define WT_STAT_CONN_CACHE_EVICTION_GET_REF_EMPTY2 1038 /*! cache: eviction currently operating in aggressive mode */ -#define WT_STAT_CONN_CACHE_EVICTION_AGGRESSIVE_SET 1037 +#define WT_STAT_CONN_CACHE_EVICTION_AGGRESSIVE_SET 1039 /*! cache: eviction server candidate queue empty when topping up */ -#define WT_STAT_CONN_CACHE_EVICTION_QUEUE_EMPTY 1038 +#define WT_STAT_CONN_CACHE_EVICTION_QUEUE_EMPTY 1040 /*! cache: eviction server candidate queue not empty when topping up */ -#define WT_STAT_CONN_CACHE_EVICTION_QUEUE_NOT_EMPTY 1039 +#define WT_STAT_CONN_CACHE_EVICTION_QUEUE_NOT_EMPTY 1041 /*! cache: eviction server evicting pages */ -#define WT_STAT_CONN_CACHE_EVICTION_SERVER_EVICTING 1040 +#define WT_STAT_CONN_CACHE_EVICTION_SERVER_EVICTING 1042 /*! cache: eviction server populating queue, but not evicting pages */ -#define WT_STAT_CONN_CACHE_EVICTION_SERVER_NOT_EVICTING 1041 +#define WT_STAT_CONN_CACHE_EVICTION_SERVER_NOT_EVICTING 1043 /*! cache: eviction server skipped very large page */ -#define WT_STAT_CONN_CACHE_EVICTION_SERVER_TOOBIG 1042 +#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 1043 +#define WT_STAT_CONN_CACHE_EVICTION_SERVER_SLEPT 1045 /*! cache: eviction server unable to reach eviction goal */ -#define WT_STAT_CONN_CACHE_EVICTION_SLOW 1044 +#define WT_STAT_CONN_CACHE_EVICTION_SLOW 1046 /*! cache: eviction worker thread evicting pages */ -#define WT_STAT_CONN_CACHE_EVICTION_WORKER_EVICTING 1045 +#define WT_STAT_CONN_CACHE_EVICTION_WORKER_EVICTING 1047 /*! cache: failed eviction of pages that exceeded the in-memory maximum */ -#define WT_STAT_CONN_CACHE_EVICTION_FORCE_FAIL 1046 +#define WT_STAT_CONN_CACHE_EVICTION_FORCE_FAIL 1048 /*! cache: files with active eviction walks */ -#define WT_STAT_CONN_CACHE_EVICTION_WALKS_ACTIVE 1047 +#define WT_STAT_CONN_CACHE_EVICTION_WALKS_ACTIVE 1049 /*! cache: files with new eviction walks started */ -#define WT_STAT_CONN_CACHE_EVICTION_WALKS_STARTED 1048 +#define WT_STAT_CONN_CACHE_EVICTION_WALKS_STARTED 1050 /*! cache: hazard pointer blocked page eviction */ -#define WT_STAT_CONN_CACHE_EVICTION_HAZARD 1049 +#define WT_STAT_CONN_CACHE_EVICTION_HAZARD 1051 /*! cache: hazard pointer check calls */ -#define WT_STAT_CONN_CACHE_HAZARD_CHECKS 1050 +#define WT_STAT_CONN_CACHE_HAZARD_CHECKS 1052 /*! cache: hazard pointer check entries walked */ -#define WT_STAT_CONN_CACHE_HAZARD_WALKS 1051 +#define WT_STAT_CONN_CACHE_HAZARD_WALKS 1053 /*! cache: hazard pointer maximum array length */ -#define WT_STAT_CONN_CACHE_HAZARD_MAX 1052 +#define WT_STAT_CONN_CACHE_HAZARD_MAX 1054 /*! cache: in-memory page passed criteria to be split */ -#define WT_STAT_CONN_CACHE_INMEM_SPLITTABLE 1053 +#define WT_STAT_CONN_CACHE_INMEM_SPLITTABLE 1055 /*! cache: in-memory page splits */ -#define WT_STAT_CONN_CACHE_INMEM_SPLIT 1054 +#define WT_STAT_CONN_CACHE_INMEM_SPLIT 1056 /*! cache: internal pages evicted */ -#define WT_STAT_CONN_CACHE_EVICTION_INTERNAL 1055 +#define WT_STAT_CONN_CACHE_EVICTION_INTERNAL 1057 /*! cache: internal pages split during eviction */ -#define WT_STAT_CONN_CACHE_EVICTION_SPLIT_INTERNAL 1056 +#define WT_STAT_CONN_CACHE_EVICTION_SPLIT_INTERNAL 1058 /*! cache: leaf pages split during eviction */ -#define WT_STAT_CONN_CACHE_EVICTION_SPLIT_LEAF 1057 +#define WT_STAT_CONN_CACHE_EVICTION_SPLIT_LEAF 1059 /*! cache: lookaside table insert calls */ -#define WT_STAT_CONN_CACHE_LOOKASIDE_INSERT 1058 +#define WT_STAT_CONN_CACHE_LOOKASIDE_INSERT 1060 /*! cache: lookaside table remove calls */ -#define WT_STAT_CONN_CACHE_LOOKASIDE_REMOVE 1059 +#define WT_STAT_CONN_CACHE_LOOKASIDE_REMOVE 1061 /*! cache: maximum bytes configured */ -#define WT_STAT_CONN_CACHE_BYTES_MAX 1060 +#define WT_STAT_CONN_CACHE_BYTES_MAX 1062 /*! cache: maximum page size at eviction */ -#define WT_STAT_CONN_CACHE_EVICTION_MAXIMUM_PAGE_SIZE 1061 +#define WT_STAT_CONN_CACHE_EVICTION_MAXIMUM_PAGE_SIZE 1063 /*! cache: modified pages evicted */ -#define WT_STAT_CONN_CACHE_EVICTION_DIRTY 1062 +#define WT_STAT_CONN_CACHE_EVICTION_DIRTY 1064 /*! cache: modified pages evicted by application threads */ -#define WT_STAT_CONN_CACHE_EVICTION_APP_DIRTY 1063 +#define WT_STAT_CONN_CACHE_EVICTION_APP_DIRTY 1065 /*! cache: page split during eviction deepened the tree */ -#define WT_STAT_CONN_CACHE_EVICTION_DEEPEN 1064 +#define WT_STAT_CONN_CACHE_EVICTION_DEEPEN 1066 /*! cache: page written requiring lookaside records */ -#define WT_STAT_CONN_CACHE_WRITE_LOOKASIDE 1065 +#define WT_STAT_CONN_CACHE_WRITE_LOOKASIDE 1067 /*! cache: pages currently held in the cache */ -#define WT_STAT_CONN_CACHE_PAGES_INUSE 1066 +#define WT_STAT_CONN_CACHE_PAGES_INUSE 1068 /*! cache: pages evicted because they exceeded the in-memory maximum */ -#define WT_STAT_CONN_CACHE_EVICTION_FORCE 1067 +#define WT_STAT_CONN_CACHE_EVICTION_FORCE 1069 /*! cache: pages evicted because they had chains of deleted items */ -#define WT_STAT_CONN_CACHE_EVICTION_FORCE_DELETE 1068 +#define WT_STAT_CONN_CACHE_EVICTION_FORCE_DELETE 1070 /*! cache: pages evicted by application threads */ -#define WT_STAT_CONN_CACHE_EVICTION_APP 1069 +#define WT_STAT_CONN_CACHE_EVICTION_APP 1071 /*! cache: pages queued for eviction */ -#define WT_STAT_CONN_CACHE_EVICTION_PAGES_QUEUED 1070 +#define WT_STAT_CONN_CACHE_EVICTION_PAGES_QUEUED 1072 /*! cache: pages queued for urgent eviction */ -#define WT_STAT_CONN_CACHE_EVICTION_PAGES_QUEUED_OLDEST 1071 +#define WT_STAT_CONN_CACHE_EVICTION_PAGES_QUEUED_OLDEST 1073 /*! cache: pages read into cache */ -#define WT_STAT_CONN_CACHE_READ 1072 +#define WT_STAT_CONN_CACHE_READ 1074 /*! cache: pages read into cache requiring lookaside entries */ -#define WT_STAT_CONN_CACHE_READ_LOOKASIDE 1073 +#define WT_STAT_CONN_CACHE_READ_LOOKASIDE 1075 /*! cache: pages requested from the cache */ -#define WT_STAT_CONN_CACHE_PAGES_REQUESTED 1074 +#define WT_STAT_CONN_CACHE_PAGES_REQUESTED 1076 /*! cache: pages seen by eviction walk */ -#define WT_STAT_CONN_CACHE_EVICTION_PAGES_SEEN 1075 +#define WT_STAT_CONN_CACHE_EVICTION_PAGES_SEEN 1077 /*! cache: pages selected for eviction unable to be evicted */ -#define WT_STAT_CONN_CACHE_EVICTION_FAIL 1076 +#define WT_STAT_CONN_CACHE_EVICTION_FAIL 1078 /*! cache: pages walked for eviction */ -#define WT_STAT_CONN_CACHE_EVICTION_WALK 1077 +#define WT_STAT_CONN_CACHE_EVICTION_WALK 1079 /*! cache: pages written from cache */ -#define WT_STAT_CONN_CACHE_WRITE 1078 +#define WT_STAT_CONN_CACHE_WRITE 1080 /*! cache: pages written requiring in-memory restoration */ -#define WT_STAT_CONN_CACHE_WRITE_RESTORE 1079 +#define WT_STAT_CONN_CACHE_WRITE_RESTORE 1081 /*! cache: percentage overhead */ -#define WT_STAT_CONN_CACHE_OVERHEAD 1080 +#define WT_STAT_CONN_CACHE_OVERHEAD 1082 /*! cache: tracked bytes belonging to internal pages in the cache */ -#define WT_STAT_CONN_CACHE_BYTES_INTERNAL 1081 +#define WT_STAT_CONN_CACHE_BYTES_INTERNAL 1083 /*! cache: tracked bytes belonging to leaf pages in the cache */ -#define WT_STAT_CONN_CACHE_BYTES_LEAF 1082 +#define WT_STAT_CONN_CACHE_BYTES_LEAF 1084 /*! cache: tracked bytes belonging to overflow pages in the cache */ -#define WT_STAT_CONN_CACHE_BYTES_OVERFLOW 1083 +#define WT_STAT_CONN_CACHE_BYTES_OVERFLOW 1085 /*! cache: tracked dirty bytes in the cache */ -#define WT_STAT_CONN_CACHE_BYTES_DIRTY 1084 +#define WT_STAT_CONN_CACHE_BYTES_DIRTY 1086 /*! cache: tracked dirty pages in the cache */ -#define WT_STAT_CONN_CACHE_PAGES_DIRTY 1085 +#define WT_STAT_CONN_CACHE_PAGES_DIRTY 1087 /*! cache: unmodified pages evicted */ -#define WT_STAT_CONN_CACHE_EVICTION_CLEAN 1086 +#define WT_STAT_CONN_CACHE_EVICTION_CLEAN 1088 /*! connection: auto adjusting condition resets */ -#define WT_STAT_CONN_COND_AUTO_WAIT_RESET 1087 +#define WT_STAT_CONN_COND_AUTO_WAIT_RESET 1089 /*! connection: auto adjusting condition wait calls */ -#define WT_STAT_CONN_COND_AUTO_WAIT 1088 +#define WT_STAT_CONN_COND_AUTO_WAIT 1090 /*! connection: files currently open */ -#define WT_STAT_CONN_FILE_OPEN 1089 +#define WT_STAT_CONN_FILE_OPEN 1091 /*! connection: memory allocations */ -#define WT_STAT_CONN_MEMORY_ALLOCATION 1090 +#define WT_STAT_CONN_MEMORY_ALLOCATION 1092 /*! connection: memory frees */ -#define WT_STAT_CONN_MEMORY_FREE 1091 +#define WT_STAT_CONN_MEMORY_FREE 1093 /*! connection: memory re-allocations */ -#define WT_STAT_CONN_MEMORY_GROW 1092 +#define WT_STAT_CONN_MEMORY_GROW 1094 /*! connection: pthread mutex condition wait calls */ -#define WT_STAT_CONN_COND_WAIT 1093 +#define WT_STAT_CONN_COND_WAIT 1095 /*! connection: pthread mutex shared lock read-lock calls */ -#define WT_STAT_CONN_RWLOCK_READ 1094 +#define WT_STAT_CONN_RWLOCK_READ 1096 /*! connection: pthread mutex shared lock write-lock calls */ -#define WT_STAT_CONN_RWLOCK_WRITE 1095 +#define WT_STAT_CONN_RWLOCK_WRITE 1097 /*! connection: total fsync I/Os */ -#define WT_STAT_CONN_FSYNC_IO 1096 +#define WT_STAT_CONN_FSYNC_IO 1098 /*! connection: total read I/Os */ -#define WT_STAT_CONN_READ_IO 1097 +#define WT_STAT_CONN_READ_IO 1099 /*! connection: total write I/Os */ -#define WT_STAT_CONN_WRITE_IO 1098 +#define WT_STAT_CONN_WRITE_IO 1100 /*! cursor: cursor create calls */ -#define WT_STAT_CONN_CURSOR_CREATE 1099 +#define WT_STAT_CONN_CURSOR_CREATE 1101 /*! cursor: cursor insert calls */ -#define WT_STAT_CONN_CURSOR_INSERT 1100 +#define WT_STAT_CONN_CURSOR_INSERT 1102 /*! cursor: cursor next calls */ -#define WT_STAT_CONN_CURSOR_NEXT 1101 +#define WT_STAT_CONN_CURSOR_NEXT 1103 /*! cursor: cursor prev calls */ -#define WT_STAT_CONN_CURSOR_PREV 1102 +#define WT_STAT_CONN_CURSOR_PREV 1104 /*! cursor: cursor remove calls */ -#define WT_STAT_CONN_CURSOR_REMOVE 1103 +#define WT_STAT_CONN_CURSOR_REMOVE 1105 /*! cursor: cursor reset calls */ -#define WT_STAT_CONN_CURSOR_RESET 1104 +#define WT_STAT_CONN_CURSOR_RESET 1106 /*! cursor: cursor restarted searches */ -#define WT_STAT_CONN_CURSOR_RESTART 1105 +#define WT_STAT_CONN_CURSOR_RESTART 1107 /*! cursor: cursor search calls */ -#define WT_STAT_CONN_CURSOR_SEARCH 1106 +#define WT_STAT_CONN_CURSOR_SEARCH 1108 /*! cursor: cursor search near calls */ -#define WT_STAT_CONN_CURSOR_SEARCH_NEAR 1107 +#define WT_STAT_CONN_CURSOR_SEARCH_NEAR 1109 /*! cursor: cursor update calls */ -#define WT_STAT_CONN_CURSOR_UPDATE 1108 +#define WT_STAT_CONN_CURSOR_UPDATE 1110 /*! cursor: truncate calls */ -#define WT_STAT_CONN_CURSOR_TRUNCATE 1109 +#define WT_STAT_CONN_CURSOR_TRUNCATE 1111 /*! data-handle: connection data handles currently active */ -#define WT_STAT_CONN_DH_CONN_HANDLE_COUNT 1110 +#define WT_STAT_CONN_DH_CONN_HANDLE_COUNT 1112 /*! data-handle: connection sweep candidate became referenced */ -#define WT_STAT_CONN_DH_SWEEP_REF 1111 +#define WT_STAT_CONN_DH_SWEEP_REF 1113 /*! data-handle: connection sweep dhandles closed */ -#define WT_STAT_CONN_DH_SWEEP_CLOSE 1112 +#define WT_STAT_CONN_DH_SWEEP_CLOSE 1114 /*! data-handle: connection sweep dhandles removed from hash list */ -#define WT_STAT_CONN_DH_SWEEP_REMOVE 1113 +#define WT_STAT_CONN_DH_SWEEP_REMOVE 1115 /*! data-handle: connection sweep time-of-death sets */ -#define WT_STAT_CONN_DH_SWEEP_TOD 1114 +#define WT_STAT_CONN_DH_SWEEP_TOD 1116 /*! data-handle: connection sweeps */ -#define WT_STAT_CONN_DH_SWEEPS 1115 +#define WT_STAT_CONN_DH_SWEEPS 1117 /*! data-handle: session dhandles swept */ -#define WT_STAT_CONN_DH_SESSION_HANDLES 1116 +#define WT_STAT_CONN_DH_SESSION_HANDLES 1118 /*! data-handle: session sweep attempts */ -#define WT_STAT_CONN_DH_SESSION_SWEEPS 1117 +#define WT_STAT_CONN_DH_SESSION_SWEEPS 1119 /*! log: busy returns attempting to switch slots */ -#define WT_STAT_CONN_LOG_SLOT_SWITCH_BUSY 1118 +#define WT_STAT_CONN_LOG_SLOT_SWITCH_BUSY 1120 /*! log: consolidated slot closures */ -#define WT_STAT_CONN_LOG_SLOT_CLOSES 1119 +#define WT_STAT_CONN_LOG_SLOT_CLOSES 1121 /*! log: consolidated slot join races */ -#define WT_STAT_CONN_LOG_SLOT_RACES 1120 +#define WT_STAT_CONN_LOG_SLOT_RACES 1122 /*! log: consolidated slot join transitions */ -#define WT_STAT_CONN_LOG_SLOT_TRANSITIONS 1121 +#define WT_STAT_CONN_LOG_SLOT_TRANSITIONS 1123 /*! log: consolidated slot joins */ -#define WT_STAT_CONN_LOG_SLOT_JOINS 1122 +#define WT_STAT_CONN_LOG_SLOT_JOINS 1124 /*! log: consolidated slot unbuffered writes */ -#define WT_STAT_CONN_LOG_SLOT_UNBUFFERED 1123 +#define WT_STAT_CONN_LOG_SLOT_UNBUFFERED 1125 /*! log: log bytes of payload data */ -#define WT_STAT_CONN_LOG_BYTES_PAYLOAD 1124 +#define WT_STAT_CONN_LOG_BYTES_PAYLOAD 1126 /*! log: log bytes written */ -#define WT_STAT_CONN_LOG_BYTES_WRITTEN 1125 +#define WT_STAT_CONN_LOG_BYTES_WRITTEN 1127 /*! log: log files manually zero-filled */ -#define WT_STAT_CONN_LOG_ZERO_FILLS 1126 +#define WT_STAT_CONN_LOG_ZERO_FILLS 1128 /*! log: log flush operations */ -#define WT_STAT_CONN_LOG_FLUSH 1127 +#define WT_STAT_CONN_LOG_FLUSH 1129 /*! log: log force write operations */ -#define WT_STAT_CONN_LOG_FORCE_WRITE 1128 +#define WT_STAT_CONN_LOG_FORCE_WRITE 1130 /*! log: log force write operations skipped */ -#define WT_STAT_CONN_LOG_FORCE_WRITE_SKIP 1129 +#define WT_STAT_CONN_LOG_FORCE_WRITE_SKIP 1131 /*! log: log records compressed */ -#define WT_STAT_CONN_LOG_COMPRESS_WRITES 1130 +#define WT_STAT_CONN_LOG_COMPRESS_WRITES 1132 /*! log: log records not compressed */ -#define WT_STAT_CONN_LOG_COMPRESS_WRITE_FAILS 1131 +#define WT_STAT_CONN_LOG_COMPRESS_WRITE_FAILS 1133 /*! log: log records too small to compress */ -#define WT_STAT_CONN_LOG_COMPRESS_SMALL 1132 +#define WT_STAT_CONN_LOG_COMPRESS_SMALL 1134 /*! log: log release advances write LSN */ -#define WT_STAT_CONN_LOG_RELEASE_WRITE_LSN 1133 +#define WT_STAT_CONN_LOG_RELEASE_WRITE_LSN 1135 /*! log: log scan operations */ -#define WT_STAT_CONN_LOG_SCANS 1134 +#define WT_STAT_CONN_LOG_SCANS 1136 /*! log: log scan records requiring two reads */ -#define WT_STAT_CONN_LOG_SCAN_REREADS 1135 +#define WT_STAT_CONN_LOG_SCAN_REREADS 1137 /*! log: log server thread advances write LSN */ -#define WT_STAT_CONN_LOG_WRITE_LSN 1136 +#define WT_STAT_CONN_LOG_WRITE_LSN 1138 /*! log: log server thread write LSN walk skipped */ -#define WT_STAT_CONN_LOG_WRITE_LSN_SKIP 1137 +#define WT_STAT_CONN_LOG_WRITE_LSN_SKIP 1139 /*! log: log sync operations */ -#define WT_STAT_CONN_LOG_SYNC 1138 +#define WT_STAT_CONN_LOG_SYNC 1140 /*! log: log sync time duration (usecs) */ -#define WT_STAT_CONN_LOG_SYNC_DURATION 1139 +#define WT_STAT_CONN_LOG_SYNC_DURATION 1141 /*! log: log sync_dir operations */ -#define WT_STAT_CONN_LOG_SYNC_DIR 1140 +#define WT_STAT_CONN_LOG_SYNC_DIR 1142 /*! log: log sync_dir time duration (usecs) */ -#define WT_STAT_CONN_LOG_SYNC_DIR_DURATION 1141 +#define WT_STAT_CONN_LOG_SYNC_DIR_DURATION 1143 /*! log: log write operations */ -#define WT_STAT_CONN_LOG_WRITES 1142 +#define WT_STAT_CONN_LOG_WRITES 1144 /*! log: logging bytes consolidated */ -#define WT_STAT_CONN_LOG_SLOT_CONSOLIDATED 1143 +#define WT_STAT_CONN_LOG_SLOT_CONSOLIDATED 1145 /*! log: maximum log file size */ -#define WT_STAT_CONN_LOG_MAX_FILESIZE 1144 +#define WT_STAT_CONN_LOG_MAX_FILESIZE 1146 /*! log: number of pre-allocated log files to create */ -#define WT_STAT_CONN_LOG_PREALLOC_MAX 1145 +#define WT_STAT_CONN_LOG_PREALLOC_MAX 1147 /*! log: pre-allocated log files not ready and missed */ -#define WT_STAT_CONN_LOG_PREALLOC_MISSED 1146 +#define WT_STAT_CONN_LOG_PREALLOC_MISSED 1148 /*! log: pre-allocated log files prepared */ -#define WT_STAT_CONN_LOG_PREALLOC_FILES 1147 +#define WT_STAT_CONN_LOG_PREALLOC_FILES 1149 /*! log: pre-allocated log files used */ -#define WT_STAT_CONN_LOG_PREALLOC_USED 1148 +#define WT_STAT_CONN_LOG_PREALLOC_USED 1150 /*! log: records processed by log scan */ -#define WT_STAT_CONN_LOG_SCAN_RECORDS 1149 +#define WT_STAT_CONN_LOG_SCAN_RECORDS 1151 /*! log: total in-memory size of compressed records */ -#define WT_STAT_CONN_LOG_COMPRESS_MEM 1150 +#define WT_STAT_CONN_LOG_COMPRESS_MEM 1152 /*! log: total log buffer size */ -#define WT_STAT_CONN_LOG_BUFFER_SIZE 1151 +#define WT_STAT_CONN_LOG_BUFFER_SIZE 1153 /*! log: total size of compressed records */ -#define WT_STAT_CONN_LOG_COMPRESS_LEN 1152 +#define WT_STAT_CONN_LOG_COMPRESS_LEN 1154 /*! log: written slots coalesced */ -#define WT_STAT_CONN_LOG_SLOT_COALESCED 1153 +#define WT_STAT_CONN_LOG_SLOT_COALESCED 1155 /*! log: yields waiting for previous log file close */ -#define WT_STAT_CONN_LOG_CLOSE_YIELDS 1154 +#define WT_STAT_CONN_LOG_CLOSE_YIELDS 1156 /*! reconciliation: fast-path pages deleted */ -#define WT_STAT_CONN_REC_PAGE_DELETE_FAST 1155 +#define WT_STAT_CONN_REC_PAGE_DELETE_FAST 1157 /*! reconciliation: page reconciliation calls */ -#define WT_STAT_CONN_REC_PAGES 1156 +#define WT_STAT_CONN_REC_PAGES 1158 /*! reconciliation: page reconciliation calls for eviction */ -#define WT_STAT_CONN_REC_PAGES_EVICTION 1157 +#define WT_STAT_CONN_REC_PAGES_EVICTION 1159 /*! reconciliation: pages deleted */ -#define WT_STAT_CONN_REC_PAGE_DELETE 1158 +#define WT_STAT_CONN_REC_PAGE_DELETE 1160 /*! reconciliation: split bytes currently awaiting free */ -#define WT_STAT_CONN_REC_SPLIT_STASHED_BYTES 1159 +#define WT_STAT_CONN_REC_SPLIT_STASHED_BYTES 1161 /*! reconciliation: split objects currently awaiting free */ -#define WT_STAT_CONN_REC_SPLIT_STASHED_OBJECTS 1160 +#define WT_STAT_CONN_REC_SPLIT_STASHED_OBJECTS 1162 /*! session: open cursor count */ -#define WT_STAT_CONN_SESSION_CURSOR_OPEN 1161 +#define WT_STAT_CONN_SESSION_CURSOR_OPEN 1163 /*! session: open session count */ -#define WT_STAT_CONN_SESSION_OPEN 1162 +#define WT_STAT_CONN_SESSION_OPEN 1164 /*! thread-state: active filesystem fsync calls */ -#define WT_STAT_CONN_FSYNC_ACTIVE 1163 +#define WT_STAT_CONN_FSYNC_ACTIVE 1165 /*! thread-state: active filesystem read calls */ -#define WT_STAT_CONN_READ_ACTIVE 1164 +#define WT_STAT_CONN_READ_ACTIVE 1166 /*! thread-state: active filesystem write calls */ -#define WT_STAT_CONN_WRITE_ACTIVE 1165 +#define WT_STAT_CONN_WRITE_ACTIVE 1167 /*! thread-yield: page acquire busy blocked */ -#define WT_STAT_CONN_PAGE_BUSY_BLOCKED 1166 +#define WT_STAT_CONN_PAGE_BUSY_BLOCKED 1168 /*! thread-yield: page acquire eviction blocked */ -#define WT_STAT_CONN_PAGE_FORCIBLE_EVICT_BLOCKED 1167 +#define WT_STAT_CONN_PAGE_FORCIBLE_EVICT_BLOCKED 1169 /*! thread-yield: page acquire locked blocked */ -#define WT_STAT_CONN_PAGE_LOCKED_BLOCKED 1168 +#define WT_STAT_CONN_PAGE_LOCKED_BLOCKED 1170 /*! thread-yield: page acquire read blocked */ -#define WT_STAT_CONN_PAGE_READ_BLOCKED 1169 +#define WT_STAT_CONN_PAGE_READ_BLOCKED 1171 /*! thread-yield: page acquire time sleeping (usecs) */ -#define WT_STAT_CONN_PAGE_SLEEP 1170 +#define WT_STAT_CONN_PAGE_SLEEP 1172 /*! transaction: number of named snapshots created */ -#define WT_STAT_CONN_TXN_SNAPSHOTS_CREATED 1171 +#define WT_STAT_CONN_TXN_SNAPSHOTS_CREATED 1173 /*! transaction: number of named snapshots dropped */ -#define WT_STAT_CONN_TXN_SNAPSHOTS_DROPPED 1172 +#define WT_STAT_CONN_TXN_SNAPSHOTS_DROPPED 1174 /*! transaction: transaction begins */ -#define WT_STAT_CONN_TXN_BEGIN 1173 +#define WT_STAT_CONN_TXN_BEGIN 1175 /*! transaction: transaction checkpoint currently running */ -#define WT_STAT_CONN_TXN_CHECKPOINT_RUNNING 1174 +#define WT_STAT_CONN_TXN_CHECKPOINT_RUNNING 1176 /*! transaction: transaction checkpoint generation */ -#define WT_STAT_CONN_TXN_CHECKPOINT_GENERATION 1175 +#define WT_STAT_CONN_TXN_CHECKPOINT_GENERATION 1177 /*! transaction: transaction checkpoint max time (msecs) */ -#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_MAX 1176 +#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_MAX 1178 /*! transaction: transaction checkpoint min time (msecs) */ -#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_MIN 1177 +#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_MIN 1179 /*! transaction: transaction checkpoint most recent time (msecs) */ -#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_RECENT 1178 +#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_RECENT 1180 /*! transaction: transaction checkpoint total time (msecs) */ -#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_TOTAL 1179 +#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_TOTAL 1181 /*! transaction: transaction checkpoints */ -#define WT_STAT_CONN_TXN_CHECKPOINT 1180 +#define WT_STAT_CONN_TXN_CHECKPOINT 1182 /*! transaction: transaction failures due to cache overflow */ -#define WT_STAT_CONN_TXN_FAIL_CACHE 1181 +#define WT_STAT_CONN_TXN_FAIL_CACHE 1183 /*! transaction: transaction fsync calls for checkpoint after allocating * the transaction ID */ -#define WT_STAT_CONN_TXN_CHECKPOINT_FSYNC_POST 1182 +#define WT_STAT_CONN_TXN_CHECKPOINT_FSYNC_POST 1184 /*! transaction: transaction fsync calls for checkpoint before allocating * the transaction ID */ -#define WT_STAT_CONN_TXN_CHECKPOINT_FSYNC_PRE 1183 +#define WT_STAT_CONN_TXN_CHECKPOINT_FSYNC_PRE 1185 /*! transaction: transaction fsync duration for checkpoint after * allocating the transaction ID (usecs) */ -#define WT_STAT_CONN_TXN_CHECKPOINT_FSYNC_POST_DURATION 1184 +#define WT_STAT_CONN_TXN_CHECKPOINT_FSYNC_POST_DURATION 1186 /*! transaction: transaction fsync duration for checkpoint before * allocating the transaction ID (usecs) */ -#define WT_STAT_CONN_TXN_CHECKPOINT_FSYNC_PRE_DURATION 1185 +#define WT_STAT_CONN_TXN_CHECKPOINT_FSYNC_PRE_DURATION 1187 /*! transaction: transaction range of IDs currently pinned */ -#define WT_STAT_CONN_TXN_PINNED_RANGE 1186 +#define WT_STAT_CONN_TXN_PINNED_RANGE 1188 /*! transaction: transaction range of IDs currently pinned by a checkpoint */ -#define WT_STAT_CONN_TXN_PINNED_CHECKPOINT_RANGE 1187 +#define WT_STAT_CONN_TXN_PINNED_CHECKPOINT_RANGE 1189 /*! transaction: transaction range of IDs currently pinned by named * snapshots */ -#define WT_STAT_CONN_TXN_PINNED_SNAPSHOT_RANGE 1188 +#define WT_STAT_CONN_TXN_PINNED_SNAPSHOT_RANGE 1190 /*! transaction: transaction sync calls */ -#define WT_STAT_CONN_TXN_SYNC 1189 +#define WT_STAT_CONN_TXN_SYNC 1191 /*! transaction: transactions committed */ -#define WT_STAT_CONN_TXN_COMMIT 1190 +#define WT_STAT_CONN_TXN_COMMIT 1192 /*! transaction: transactions rolled back */ -#define WT_STAT_CONN_TXN_ROLLBACK 1191 +#define WT_STAT_CONN_TXN_ROLLBACK 1193 /*! * @} diff --git a/src/support/stat.c b/src/support/stat.c index ba9651a3e51..74770dbeea1 100644 --- a/src/support/stat.c +++ b/src/support/stat.c @@ -548,7 +548,9 @@ static const char * const __stats_connection_desc[] = { "block-manager: bytes written", "block-manager: mapped blocks read", "block-manager: mapped bytes read", + "cache: bytes belonging to page images in the cache", "cache: bytes currently in the cache", + "cache: bytes not belonging to page images in the cache", "cache: bytes read into cache", "cache: bytes written from cache", "cache: checkpoint blocked page eviction", @@ -770,7 +772,9 @@ __wt_stat_connection_clear_single(WT_CONNECTION_STATS *stats) stats->block_byte_write = 0; stats->block_map_read = 0; stats->block_byte_map_read = 0; + /* not clearing cache_bytes_image */ /* not clearing cache_bytes_inuse */ + /* not clearing cache_bytes_other */ stats->cache_bytes_read = 0; stats->cache_bytes_write = 0; stats->cache_eviction_checkpoint = 0; @@ -984,7 +988,9 @@ __wt_stat_connection_aggregate( to->block_byte_write += WT_STAT_READ(from, block_byte_write); to->block_map_read += WT_STAT_READ(from, block_map_read); to->block_byte_map_read += WT_STAT_READ(from, block_byte_map_read); + to->cache_bytes_image += WT_STAT_READ(from, cache_bytes_image); to->cache_bytes_inuse += WT_STAT_READ(from, cache_bytes_inuse); + to->cache_bytes_other += WT_STAT_READ(from, cache_bytes_other); to->cache_bytes_read += WT_STAT_READ(from, cache_bytes_read); to->cache_bytes_write += WT_STAT_READ(from, cache_bytes_write); to->cache_eviction_checkpoint += diff --git a/src/txn/txn_ckpt.c b/src/txn/txn_ckpt.c index 51d26b9aed6..3a6e1832f34 100644 --- a/src/txn/txn_ckpt.c +++ b/src/txn/txn_ckpt.c @@ -400,6 +400,9 @@ __txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[]) session, cfg, __wt_checkpoint_get_handles, NULL)))); WT_ERR(ret); + /* Reset the maximum page size seen by eviction. */ + conn->cache->evict_max_page_size = 0; + /* * Update the global oldest ID so we do all possible cleanup. * diff --git a/tools/wtstats/stat_data.py b/tools/wtstats/stat_data.py index 2bea123fc91..d06f1035adf 100644 --- a/tools/wtstats/stat_data.py +++ b/tools/wtstats/stat_data.py @@ -3,7 +3,9 @@ no_scale_per_second_list = [ 'async: current work queue length', 'async: maximum work queue length', + 'cache: bytes belonging to page images in the cache', 'cache: bytes currently in the cache', + 'cache: bytes not belonging to page images in the cache', 'cache: eviction currently operating in aggressive mode', 'cache: files with active eviction walks', 'cache: hazard pointer maximum array length', @@ -75,7 +77,9 @@ no_scale_per_second_list = [ ] no_clear_list = [ 'async: maximum work queue length', + 'cache: bytes belonging to page images in the cache', 'cache: bytes currently in the cache', + 'cache: bytes not belonging to page images in the cache', 'cache: eviction currently operating in aggressive mode', 'cache: files with active eviction walks', 'cache: maximum bytes configured', |