-
Type:
Task
-
Resolution: Unresolved
-
Priority:
Major - P3
-
None
-
Affects Version/s: None
-
Component/s: Cache and Eviction
-
Storage Engines - Transactions
-
543.054
-
SE Transactions - 2026-09-11
-
3
Target
An internal page whose children have been fast-truncated should be prioritised for eviction on account of that fact, by the eviction server's own scoring, and in proportion to how much of it is truncated rather than only when all of it is.
Current behaviour
1. An opportunistic all-children-deleted hint in the tree walk.
__tree_walk_internal() in src/btree/bt_walk.c sets empty_internal = true on descending into an internal page and clears it as soon as it sees a child in any state other than WT_REF_DELETED:
current_state = WT_REF_GET_STATE(ref); if (current_state != WT_REF_DELETED && !LF_ISSET(WT_READ_TRUNCATE)) empty_internal = false;
On ascending back out, a surviving flag calls __wt_evict_page_soon():
If we got all the way through an internal page and all of the child pages were deleted, mark it for eviction.
The trigger is every child deleted rather than any; it is suppressed under WT_READ_TRUNCATE; and it only fires if some walk happens to traverse the entire page, so a fully deleted subtree that nothing walks over is never flagged.
2. Eviction's own prioritisation, which pushes the other way.
__evict_priority() in src/evict/evict_walk.c has no term for deleted children. Internal pages are penalised:
#define WT_EVICT_INTL_SKEW WT_THOUSAND
if (F_ISSET(ref, WT_REF_FLAG_INTERNAL))
read_gen += WT_EVICT_INTL_SKEW;
with the rationale "we prefer to evict leaf pages". On top of that the eviction server declines internal pages outright unless it is aggressive or the tree is idle, and skips any internal page that is the parent of the last page it saw. The __wt_page_is_empty() fast path in the same function reflects the page's own reconciliation result, not its children's states.
3. A permission gate, not a priority one.
__evict_child_check() in src/evict/evict_page.c permits a parent's eviction when each deleted child's truncate is committed and visible, and returns EBUSY otherwise. It decides whether eviction is legal, never whether it is desirable.
Net effect
A partially fast-truncated internal page receives no boost at all and is ranked below an ordinary leaf. A fully truncated one is picked up only by chance of a walk. Cache is retained for subtrees that can produce no visible content.
Constraints any solution has to respect
- __evict_priority() is on the eviction walk's hot path and currently touches only the page's own fields.
- A deleted child whose truncate is not yet committed and visible will fail __evict_child_check(), so prioritising such a page wastes an eviction attempt.
- The server-level "skip internal pages unless aggressive or idle" rule in __evict_walk_target() suppresses internal-page candidates in the common case.
Related
Shares its underlying observation with the subtree walk-skip work: a fully truncated subtree is precisely the case that ticket wants to avoid reading.
- related to
-
WT-18406 Skip reading an internal page when its time aggregate shows the whole subtree is deleted and visible
-
- Closed
-