1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 06:57:46 +00:00

LibAudio: Avoid frequent read() calls in FLAC residual decode

Decoding the residual in FLAC subframes is by far the most I/O-heavy
operation in FLAC decoding, as the residual data makes up the majority
of subframe data in LPC subframes. As the residual consists of many
Rice-encoded numbers with different bit sizes for differently large
numbers, the residual decoder frequently reads only one or two bytes at
a time. As we use a normal FileInputStream, that directly translates to
many calls to the read() syscall. We can see that the I/O overhead while
FLAC decoding is quite large, and much time is spent in the read()
syscall's kernel code.

This is optimized by using a Buffered<FileInputStream> instead, leading
to 4K blocks being read at once and a large reduction in I/O overhead.

Benchmarking with the new abench utility gives a 15-20% speedup on
identical files, usually pushing FLAC decoding to 10-15x realtime speed
on common sample rates.
This commit is contained in:
kleines Filmröllchen 2021-10-03 11:39:17 +02:00 committed by Brian Gianforcaro
parent cbb2b4fe71
commit 14d330faba
2 changed files with 16 additions and 7 deletions

View file

@ -28,9 +28,14 @@ FlacLoaderPlugin::FlacLoaderPlugin(StringView path)
return;
}
m_stream = make<FlacInputStream>(Core::InputFileStream(*m_file));
auto maybe_stream = Core::InputFileStream::open_buffered(path);
if (maybe_stream.is_error()) {
m_error_string = "Can't open file stream";
return;
}
m_stream = make<FlacInputStream>(maybe_stream.release_value());
if (!m_stream) {
m_error_string = String::formatted("Can't open memory stream");
m_error_string = "Can't open file stream";
return;
}
@ -69,7 +74,7 @@ bool FlacLoaderPlugin::parse_header()
InputBitStream bit_input = [&]() -> InputBitStream {
if (m_file) {
return InputBitStream(m_stream->get<Core::InputFileStream>());
return InputBitStream(m_stream->get<Buffered<Core::InputFileStream>>());
}
return InputBitStream(m_stream->get<InputMemoryStream>());
}();