-
Type:
Improvement
-
Resolution: Unresolved
-
Priority:
Major - P3
-
None
-
Affects Version/s: None
-
Component/s: Cache and Eviction
-
None
-
Storage Engines - Transactions
-
36.368
-
SE Transactions - 2026-09-11
-
5
Motivation
Eviction decides twice whether a dirty page is worth reconciling: at queue time in _evict_skip_dirty_candidate() (src/evict/evict_walk.c) and at eviction time in _evict_review() (src/evict/evict_page.c). Both gate on WT_CONN_PRECISE_CHECKPOINT and WT_BTREE_GARBAGE_COLLECT, but wrap them differently and cover different page types, and one check is written twice.
Queue time, leaf and internal pages, only when !__wt_evict_aggressive():
else if (F_ISSET(conn, WT_CONN_PRECISE_CHECKPOINT)) { if (F_ISSET(btree, WT_BTREE_GARBAGE_COLLECT)) { (1) eviction_server_skip_pages_prune_timestamp (2) eviction_server_skip_pages_prune_timestamp_not_move } else { (3) eviction_server_skip_pages_checkpoint_timestamp } }
Eviction time, leaf pages only:
if (F_ISSET(btree, WT_BTREE_GARBAGE_COLLECT)) { (4) blocked, prune timestamp not moved } else if (F_ISSET(conn, WT_CONN_PRECISE_CHECKPOINT)) { (5) blocked, running checkpoint pinning the stable timestamp }
After WT-18410, ingest leaf pages with a stalled prune timestamp are skipped whether or not eviction is aggressive, while internal pages are skipped only when it is not. Confirm that split is intended and refactor accordingly.
Work
Deduplicate. (2) and (4) are the same comparison. __wti_evict_prune_ts_unmoved() already encapsulates it – call it from both.
Fix the flag nesting. WT_BTREE_GARBAGE_COLLECT is set purely on the ingest URI at src/btree/bt_handle.c:609, independent of WT_CONN_PRECISE_CHECKPOINT. Nesting (1) and (2) inside the precise-checkpoint flag means the prune checks silently do not run on a garbage-collected tree with precise checkpoints off. _evict_review()'s shape – garbage collect outer, precise checkpoint as else if – is the correct one. WT-18410's check in _evict_try_queue_page() works around this for leaf pages; correct the nesting and drop the workaround.
Settle the page-type gating. Evidence that all three queue-time checks should be leaf-only, matching __evict_review(): newest_commit_timestamp is maintained only by the leaf update paths (src/include/serial_inline.h:208,266,323), so (1) and (3) are already dead code on internal pages; and (4) is leaf-gated, so nothing at eviction time blocks an internal page on the prune timestamp, making (2) lost eviction rather than saved work.
Add the missing queue-time counterpart to (5). A page whose remaining dirty content sits at or below the checkpoint timestamp – non-timestamped updates leave newest_commit_timestamp == WT_TS_NONE – passes (3), gets queued, then takes EBUSY with cache_eviction_blocked_precise_checkpoint.
Unify the timestamp-unmoved helpers. rec_pinned_stable_timestamp is tested at two strictnesses: _sync_page_skip_reconcile() (src/btree/bt_sync.c:31-38) also requires rec_ckpt_snap_gen == __wt_gen(WT_GEN_CHECKPOINT), and per src/reconcile/rec_write.c:823 that stamp is set only when eviction reconciles under the published checkpoint snapshot. So checkpoint means "eviction already did this page for this checkpoint" and (5) means "anybody did." Give each form a named helper so the difference is visible at the call site, alongside _wti_evict_prune_ts_unmoved().
Placement rule. Checks that mirror an unconditional EBUSY in __evict_review() – (2)/(4) and the new queue-side (5) – are guarantees, so queueing is pure waste even under aggressive eviction and they belong before the bypass. Content heuristics (1) and (3) stay behind it. State the rule in the code.
Definition of done
- No duplicated timestamp-unmoved comparisons between evict_walk.c and evict_page.c; each condition has one named helper.
- Both sites use the same flag nesting and the same page-type gating.
- Queue-time and eviction-time rejections remain distinguishable in FTDC.
- is related to
-
WT-18410 Don't queue pages with stalled prune timestamps for eviction
-
- Closed
-