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:
parent
95b98e588b
commit
f7c0902d8d
2 changed files with 10 additions and 7 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Reference in a new issue