From 88a45e617894e5fb55163a9dd59057e5a6a018aa Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Sat, 22 May 2021 16:07:11 +0200 Subject: [PATCH] Prevent unnecessary copies during audio processing We did a ton of work earlier to make sure we can reuse these objects, but `auto` implies the type is never a reference type, and we were thus unnecessarily creating copies every iteration, kind of defeating the purpose of doing all of this in the first place. We could do some template trickery here, but it's also safe to just make the persistent object thread local since the actual objects aren't that large. --- src/common/communication/vst3.h | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/common/communication/vst3.h b/src/common/communication/vst3.h index 51f5376b..5642823f 100644 --- a/src/common/communication/vst3.h +++ b/src/common/communication/vst3.h @@ -206,22 +206,25 @@ class Vst3MessageHandler : public AdHocSocketHandler { // using const auto process_message = [&](boost::asio::local::stream_protocol::socket& socket) { + // The persistent buffer is only used when the + // `persistent_buffers` template value is enabled, but we'll + // always use the thread local persistent object. Because of + // loading and storing state the buffer can grow a lot in size + // which is why we might not want to reuse that for tasks that + // don't need to be realtime safe, but the object has a fixed + // size. Normally reusing this object doesn't make much sense + // since it's a variant and it will likely have to be recreated + // every time, but on the audio processor side we store the + // actual variant within an object and we then use some hackery + // to always keep the large process data object in memory. thread_local std::vector persistent_buffer{}; - // This is an `std::variant<>`, so this will actually - // persistently store a copy of all possible requests even if - // we're only interested in the process data, since that's the - // only object where allocations can happen. The other objects - // we're storing here are very small, so the extra wasted memory - // shouldn't matter much. - thread_local std::optional persistent_object( - persistent_buffers ? std::make_optional() - : std::nullopt); + thread_local Request persistent_object; - auto request = + auto& request = persistent_buffers - ? read_object(socket, *persistent_object, + ? read_object(socket, persistent_object, persistent_buffer) - : read_object(socket); + : read_object(socket, persistent_object); // See the comment in `receive_into()` for more information bool should_log_response = false;