diff options
Diffstat (limited to 'src/third_party/wiredtiger/src/include/btree.i')
-rw-r--r-- | src/third_party/wiredtiger/src/include/btree.i | 75 |
1 files changed, 57 insertions, 18 deletions
diff --git a/src/third_party/wiredtiger/src/include/btree.i b/src/third_party/wiredtiger/src/include/btree.i index 19b300908b1..560cc8eb212 100644 --- a/src/third_party/wiredtiger/src/include/btree.i +++ b/src/third_party/wiredtiger/src/include/btree.i @@ -28,6 +28,17 @@ __wt_page_is_empty(WT_PAGE *page) } /* + * __wt_page_evict_clean -- + * Return if the page can be evicted without dirtying the tree. + */ +static inline bool +__wt_page_evict_clean(WT_PAGE *page) +{ + return (page->modify == NULL || (page->modify->write_gen == 0 && + page->modify->rec_result == 0)); +} + +/* * __wt_page_is_modified -- * Return if the page is dirty. */ @@ -1268,8 +1279,7 @@ __wt_leaf_page_can_split(WT_SESSION_IMPL *session, WT_PAGE *page) /* * __wt_page_evict_retry -- - * Check if there has been transaction progress since the last eviction - * attempt. + * Avoid busy-spinning attempting to evict the same page all the time. */ static inline bool __wt_page_evict_retry(WT_SESSION_IMPL *session, WT_PAGE *page) @@ -1279,29 +1289,43 @@ __wt_page_evict_retry(WT_SESSION_IMPL *session, WT_PAGE *page) txn_global = &S2C(session)->txn_global; - if ((mod = page->modify) == NULL) + /* + * If the page hasn't been through one round of update/restore, give it + * a try. + */ + if ((mod = page->modify) == NULL || !mod->update_restored) return (true); - if (txn_global->current != txn_global->oldest_id && - mod->last_eviction_id == __wt_txn_oldest_id(session)) - return (false); + /* + * Retry if a reasonable amount of eviction time has passed, the + * choice of 5 eviction passes as a reasonable amount of time is + * currently pretty arbitrary. + */ + if (__wt_cache_aggressive(session) || + mod->last_evict_pass_gen + 5 < S2C(session)->cache->evict_pass_gen) + return (true); + + /* Retry if the global transaction state has moved forward. */ + if (txn_global->current == txn_global->oldest_id || + mod->last_eviction_id != __wt_txn_oldest_id(session)) + return (true); #ifdef HAVE_TIMESTAMPS { bool same_timestamp; - if (__wt_timestamp_iszero(&mod->last_eviction_timestamp)) + same_timestamp = false; + if (!__wt_timestamp_iszero(&mod->last_eviction_timestamp)) + WT_WITH_TIMESTAMP_READLOCK(session, &txn_global->rwlock, + same_timestamp = __wt_timestamp_cmp( + &mod->last_eviction_timestamp, + &txn_global->pinned_timestamp) == 0); + if (!same_timestamp) return (true); - - WT_WITH_TIMESTAMP_READLOCK(session, &txn_global->rwlock, - same_timestamp = __wt_timestamp_cmp( - &mod->last_eviction_timestamp, &txn_global->pinned_timestamp) == 0); - if (same_timestamp) - return (false); } #endif - return (true); + return (false); } /* @@ -1336,6 +1360,14 @@ __wt_page_can_evict(WT_SESSION_IMPL *session, WT_REF *ref, bool *inmem_splitp) return (false); /* + * If the page was restored after a truncate, it can't be evicted until + * the truncate completes. + */ + if (ref->page_del != NULL && !__wt_txn_visible_all(session, + ref->page_del->txnid, WT_TIMESTAMP_NULL(&ref->page_del->timestamp))) + return (false); + + /* * Check for in-memory splits before other eviction tests. If the page * should split in-memory, return success immediately and skip more * detailed eviction tests. We don't need further tests since the page @@ -1423,15 +1455,22 @@ __wt_page_release(WT_SESSION_IMPL *session, WT_REF *ref, uint32_t flags) * * Fast checks if eviction is disabled for this handle, operation or * tree, then perform a general check if eviction will be possible. + * + * Checkpoint should not queue pages for urgent eviction if it cannot + * evict them immediately: there is a special exemption that allows + * checkpoint to evict dirty pages in a tree that is being + * checkpointed, and no other thread can help with that. */ page = ref->page; if (WT_READGEN_EVICT_SOON(page->read_gen) && btree->evict_disabled == 0 && __wt_page_can_evict(session, ref, &inmem_split)) { - if ((LF_ISSET(WT_READ_NO_SPLIT) || (!inmem_split && - F_ISSET(session, WT_SESSION_NO_RECONCILE)))) - __wt_page_evict_urgent(session, ref); - else { + if (!__wt_page_evict_clean(page) && + (LF_ISSET(WT_READ_NO_SPLIT) || (!inmem_split && + F_ISSET(session, WT_SESSION_NO_RECONCILE)))) { + if (!WT_SESSION_IS_CHECKPOINT(session)) + __wt_page_evict_urgent(session, ref); + } else { WT_RET_BUSY_OK(__wt_page_release_evict(session, ref)); return (0); } |