diff --git a/plans/bootstrap.md b/plans/bootstrap.md index 5646e9a3..514bf00a 100644 --- a/plans/bootstrap.md +++ b/plans/bootstrap.md @@ -301,7 +301,8 @@ decoder, exercised from two callers `PageWalker::walk_page`: -- pd_lower / pd_upper bounds-check; empty-page fast path +- all-zero `PageIsNew` fast path (`pd_upper == 0` plus full-page zero check) +- pd_lower / pd_upper bounds-check; initialized-empty fast path (`pd_lower == 24 && pd_upper == 8192`) - iterate `(pd_lower - 24) / 4` `ItemIdData` slots - `LP_NORMAL` slots dispatch `decode_on_page_tuple`; other lp_flags diff --git a/src/backfill/backup_page_walk.rs b/src/backfill/backup_page_walk.rs index 33a1ad1e..181aefcb 100644 --- a/src/backfill/backup_page_walk.rs +++ b/src/backfill/backup_page_walk.rs @@ -202,6 +202,10 @@ impl<'a> PageWalker<'a> { // pd_pagesize 18..20 pd_prune 20..24 let pd_lower = u16::from_le_bytes(page[12..14].try_into().unwrap()); let pd_upper = u16::from_le_bytes(page[14..16].try_into().unwrap()); + if pd_upper == 0 && page.iter().all(|&byte| byte == 0) { + stats.pages_walked += 1; + return Ok(()); + } if pd_lower as usize == SIZE_OF_PAGE_HEADER && pd_upper as usize == PAGE_BYTES { // Fresh / empty page stats.pages_walked += 1; @@ -779,6 +783,20 @@ mod tests { assert_eq!(stats.slots_seen, 0); } + #[test] + fn page_walker_handles_zero_page() { + let rel = make_rel(); + let walker = PageWalker::new(&rel, 0); + let mut out = Vec::new(); + let mut stats = PageWalkStats::default(); + walker + .walk_page(&[0; PAGE_BYTES], 0, &mut out, &mut stats) + .unwrap(); + assert!(out.is_empty()); + assert_eq!(stats.pages_walked, 1); + assert_eq!(stats.slots_seen, 0); + } + #[test] fn page_walker_skips_lp_dead_slots() { let rel = make_rel();