decode_stack tests: box the decoded result on the small thread, measured thread sizes; doctest fixture serde-able

Measured on Yggdrasil: the decode needs 56 KiB (Wide32) and 80 KiB (Largest) in
debug on a thread that returns a bool; returning the record through
std::thread's own frames adds several copies of it, so the tests box it and
size threads at 96 KiB and from 160 KiB.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-10-14 19:56:57 +02:00
commit f7c0902d8d
2 changed files with 10 additions and 7 deletions

View file

@ -655,7 +655,7 @@ const DECODE_STACK_SEGMENT: usize = 2 * 1024 * 1024;
/// #[cultcache(key = 0)]
/// bytes: Vec<u8>,
/// #[cultcache(key = 1)]
/// header: [u8; 16 * 1024 - 64],
/// header: [[u64; 32]; 63],
/// }
/// ```
pub const MAX_RECORD_INLINE_BYTES: usize = 16 * 1024;

View file

@ -177,8 +177,11 @@ fn empty_wide() -> Wide32 {
}
}
/// The decode alone runs on the small thread. Its result is boxed there so that the thread's own
/// return machinery, which would hold several more copies of a large record in a debug build, does
/// not count against the stack under test; what the caller's frames hold is the caller's to size.
fn decode_on<T: DeserializeOwned + Send + 'static>(stack: usize, bytes: Vec<u8>) -> anyhow::Result<T> {
on_stack(stack, move || decode_payload::<T>(&bytes))
*on_stack(stack, move || Box::new(decode_payload::<T>(&bytes)))
}
#[test]
@ -312,10 +315,10 @@ fn a_wide_record_100_levels_deep_decodes_on_a_1mib_thread() {
}
#[test]
fn a_wide_record_decodes_on_a_64kib_thread_at_one_level_and_at_the_limit() {
in_child("a_wide_record_decodes_on_a_64kib_thread_at_one_level_and_at_the_limit", || {
decode_wide_chain(1, 64 * KIB);
decode_wide_chain(MAX_PAYLOAD_DEPTH - 1, 64 * KIB);
fn a_wide_record_decodes_on_a_96kib_thread_at_one_level_and_at_the_limit() {
in_child("a_wide_record_decodes_on_a_96kib_thread_at_one_level_and_at_the_limit", || {
decode_wide_chain(1, 96 * KIB);
decode_wide_chain(MAX_PAYLOAD_DEPTH - 1, 96 * KIB);
});
}
@ -339,7 +342,7 @@ fn the_largest_record_at_the_limit_decodes_on_every_thread_size() {
assert!(check_payload_depth(&rmp_serde::to_vec(&union_chain(128)).unwrap()).is_err());
(records, unions)
});
let sizes = (128..=1024).step_by(32).map(|kib| kib * KIB).chain([1536, 2048, 3072, 4096, 8192].map(|kib| kib * KIB));
let sizes = (160..=1024).step_by(32).map(|kib| kib * KIB).chain([1536, 2048, 3072, 4096, 8192].map(|kib| kib * KIB));
for size in sizes {
println!("thread of {} KiB", size / KIB);
let decoded = decode_on::<Largest>(size, records.clone()).unwrap();