From f534664e1948c8023aaef366d4fb58a184825f92 Mon Sep 17 00:00:00 2001 From: not-matthias Date: Thu, 5 Nov 2026 18:53:34 +0100 Subject: [PATCH] perf(runner-shared): read the memtrack event stream through a 1 MiB buffer Stack records carry an 8 KiB byte field, which `rmp_serde` reads with `Read::take(..).read_to_end`. With the default 8 KiB `BufReader` almost every such read crosses a buffer refill. A 1 MiB buffer keeps those reads inside the buffer; on a 2.3 GiB artifact with 14.6M stack records this took the memory callgraph parse from about 52 s to 48 s. Refs COD-4142 --- crates/runner-shared/src/artifacts/memtrack/mod.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/runner-shared/src/artifacts/memtrack/mod.rs b/crates/runner-shared/src/artifacts/memtrack/mod.rs index 962095077..f799ada9e 100644 --- a/crates/runner-shared/src/artifacts/memtrack/mod.rs +++ b/crates/runner-shared/src/artifacts/memtrack/mod.rs @@ -26,13 +26,19 @@ impl super::ArtifactExt for MemtrackArtifact { impl MemtrackArtifact { /// The msgpack decoder reads a few bytes per call, so the decompressed /// stream is buffered rather than read straight from the zstd decoder. + /// The buffer is sized well above a stack record's 8 KiB byte field. #[allow(clippy::type_complexity)] pub fn decode_streamed( reader: R, ) -> anyhow::Result>>>> { + const BUFFER_SIZE: usize = 1024 * 1024; + let decoder = zstd::Decoder::new(reader)?; Ok(MemtrackEventStream { - deserializer: rmp_serde::Deserializer::new(BufReader::new(decoder)), + deserializer: rmp_serde::Deserializer::new(BufReader::with_capacity( + BUFFER_SIZE, + decoder, + )), }) }