Files
photocraft/crates/codecs/tests/pnm_peak_memory.rs
T
Valentin KleinandClaude Opus 5.5 59820ecafb Codecs: decode PNM straight into the budgeted output buffer (#2938) (#3291)
Limits::max_alloc budgets the decoded pixel buffer, but the PNM decoder
collected one u32 per sample first (4x an 8-bit image, plus a u16 copy
for 16-bit) and PFM built a Vec<f32> beside the output bytes. Samples are
now rescaled and written straight into the native-endian output buffer
(reserved fallibly), so the only header-sized allocation is the one
Limits::check already charged.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:16:07 -04:00

37 lines
1.7 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! #2938: `Limits::max_alloc` budgets the decoded pixel buffer, so the PNM decoder must not build a
//! wider scratch copy (it used to collect one `u32` per sample, four times an 8-bit image) next to it.
//!
//! This file holds a single test so it runs in its own process: it reads the process's peak RSS
//! (`VmHWM`, Linux only) and nothing else may allocate meanwhile.
#[cfg(target_os = "linux")]
fn peak_rss_bytes() -> Option<u64> {
let status = std::fs::read_to_string("/proc/self/status").ok()?;
let line = status.lines().find(|l| l.starts_with("VmHWM:"))?;
let kib: u64 = line.trim_start_matches("VmHWM:").trim().trim_end_matches("kB").trim().parse().ok()?;
Some(kib * 1024)
}
#[cfg(target_os = "linux")]
#[test]
fn pnm_decode_peak_memory_stays_near_the_output_size() {
use photocraft_codecs::*;
const SIDE: u32 = 4096; // 16 MiB of 8-bit gray output
let out_bytes = (SIDE * SIDE) as u64;
let mut file = format!("P5\n{SIDE} {SIDE}\n255\n").into_bytes();
file.extend((0..out_bytes).map(|i| (i % 251) as u8));
// Writing 5 resets the peak RSS to the current RSS; skip where the kernel doesn't allow it.
if std::fs::write("/proc/self/clear_refs", "5").is_err() {
return;
}
let Some(before) = peak_rss_bytes() else { return };
let img = decode(&file).unwrap();
let after = peak_rss_bytes().unwrap();
assert_eq!(img.data().len() as u64, out_bytes);
assert_eq!(img.data()[300], (300 % 251) as u8);
// The output buffer plus slack; a `u32`-per-sample scratch copy alone would be 4× it.
let grown = after.saturating_sub(before);
assert!(grown < 2 * out_bytes, "decoding a {out_bytes} byte image raised peak RSS by {grown} bytes");
}