perf(delivery): stream verified restore file pages

This commit is contained in:
2026-10-28 21:35:41 +08:00
parent 60a0dad94f
commit a436c659e9
3 changed files with 51 additions and 0 deletions
@@ -335,6 +335,12 @@ impl Roots {
retain, retain,
&mut buffer, &mut buffer,
)?; )?;
// These historical destination bytes have already been synchronized
// and fully verified. Keep their clean pages out of this finite
// restore working set; all descriptor/path witnesses still follow.
remaining(deadline)?;
rustix::fs::fadvise(&input, 0, None, rustix::fs::Advice::DontNeed)
.map_err(|_| Error::Filesystem)?;
if stamp(&input.metadata().map_err(|_| Error::Filesystem)?)? != pending.witness if stamp(&input.metadata().map_err(|_| Error::Filesystem)?)? != pending.witness
|| anchor.observed(name)? != pending.witness || anchor.observed(name)? != pending.witness
{ {
@@ -487,6 +487,46 @@ mod tests {
} }
} }
#[test]
fn streamed_verified_pages_preserve_repeated_large_bytes_and_all_witnesses() {
let fixture = files::Fixture::new();
let roots = Arc::new(fixture.roots());
let data = vec![b'v'; 8 * 1024 * 1024];
let hash = format!("{:x}", Sha256::digest(&data));
let source = fixture.source().join(&hash);
fs::write(&source, &data).unwrap();
fs::set_permissions(&source, fs::Permissions::from_mode(0o600)).unwrap();
use std::os::unix::fs::MetadataExt;
let owner = fs::metadata(&source).unwrap();
let rows = (0..3)
.map(|index| restore_io::RestoreFile {
path: format!("artifacts/stream-{index}"),
uid: owner.uid(),
gid: owner.gid(),
mode: 0o644,
bytes: data.len() as u64,
sha256: hash.clone(),
})
.collect();
let pool = Pool::new(Arc::clone(&roots)).unwrap_or_else(|_| panic!("pool"));
let verified = pool
.materialize(rows, &roots, now().unwrap() + 10_000_000_000)
.unwrap_or_else(|_| panic!("streamed verified copies"));
assert_eq!(verified.len(), 3);
for row in &verified {
roots
.final_file(row)
.unwrap_or_else(|_| panic!("final witness"));
let name = row.row.path.strip_prefix("artifacts/").unwrap();
assert_eq!(fs::read(fixture.target().join(name)).unwrap(), data);
roots
.final_file(row)
.unwrap_or_else(|_| panic!("unchanged witness"));
}
drop(pool);
roots.unchanged().unwrap_or_else(|_| panic!("root anchors"));
}
#[test] #[test]
fn request_line_requires_finite_complete_frame() { fn request_line_requires_finite_complete_frame() {
assert!(matches!( assert!(matches!(
+5
View File
@@ -515,6 +515,11 @@ The native restore helper keeps two joined threads and partitions each fixed bat
into contiguous groups that minimize the heavier byte count. Ties prefer balanced into contiguous groups that minimize the heavier byte count. Ties prefer balanced
file counts. Copy order, synchronization, complete byte readback and final file counts. Copy order, synchronization, complete byte readback and final
nine-field witnesses are preserved; no extra worker or batch capacity is added. nine-field witnesses are preserved; no extra worker or batch capacity is added.
After synchronization and complete byte verification, the native helper asks the
kernel to release clean cached pages for that restored file. Descriptor and path
witnesses are still checked afterwards. This per-file streaming hint avoids
retaining historical file contents in the fixed restore memory budget; it does
not change file bytes, durability, limits or the live filesystem checks.
Old configuration and maintenance receipts go into inactive Old configuration and maintenance receipts go into inactive
`recovery/ID/history/`. The new boot's Sandbox preparation owns cgroup recreation. `recovery/ID/history/`. The new boot's Sandbox preparation owns cgroup recreation.
Unknown/nonempty targets and differing existing files are refused; partial restores Unknown/nonempty targets and differing existing files are refused; partial restores