Profiling cfsctl oci create-layer shows fully 5.4% of the run time of the program is spent in calloc() for the buffers for inline splitstream data, presumably zero-filling. Another 1% is spent in the corresponding free().
That's the result of this dumb code in read_splitstream_chunk():
size => {
let mut data = vec![0u8; size];
reader.read_exact(&mut data)?;
Ok(Some(SplitStreamData::Inline(data)))
}
This looks like an obvious usecase for BorrowedCursor to avoid needing to initialize the memory, but the bigger win would come from not doing a new allocation each time: the caller never saves that buffer anyway, so we could use an internal Vec<u8> which we grow as-needed, returning a slice reference to it.
The main issue there is that read_splitstream_chunk() is a static method, so there's nowhere to store the buffer. We might consider merging this method into SplitStreamReader and figuring out an intelligent way to merge it with the existing inline_content: VecDeque<u8> that's already there.
Profiling
cfsctl oci create-layer
shows fully 5.4% of the run time of the program is spent incalloc()
for the buffers for inline splitstream data, presumably zero-filling. Another 1% is spent in the correspondingfree()
.That's the result of this dumb code in
read_splitstream_chunk()
:This looks like an obvious usecase for
BorrowedCursor
to avoid needing to initialize the memory, but the bigger win would come from not doing a new allocation each time: the caller never saves that buffer anyway, so we could use an internalVec<u8>
which we grow as-needed, returning a slice reference to it.The main issue there is that
read_splitstream_chunk()
is a static method, so there's nowhere to store the buffer. We might consider merging this method intoSplitStreamReader
and figuring out an intelligent way to merge it with the existinginline_content: VecDeque<u8>
that's already there.