Reuse objects in the VST3 audio processor sockets

This means that, we're now receiving into an existing `YaProcessData`
object, which should reduce the number of allocations on the Wine side
considerably. Next we should also reuse the `YaProcessDataResponse`
object.
This commit is contained in:
Robbert van der Helm
2021-05-06 16:41:11 +02:00
parent 6231ab7816
commit 0b173ecba8
+18 -6
View File
@@ -191,11 +191,15 @@ class Vst3MessageHandler : public AdHocSocketHandler<Thread> {
* @tparam F A function type in the form of `T::Response(T)` for every `T`
* in `Request`. This way we can directly deserialize into a `T::Response`
* on the side that called `receive_into(T, T::Response&)`.
* @tparam persistent_buffers Whether processing buffers should be kept
* around and reused. This is used to minimize allocations in the audio
* processing loop. These buffers will also never shrink, but that should
* not be an issue with the `IAudioProcessor` and `IComponent` functions.
* Saving and loading state is handled on the main sockets.
* @tparam persistent_buffers If enabled, we'll reuse the buffers used for
* sending and receiving serialized data as well as the objects we're
* receiving into. This avoids allocations in the audio processing loop
* (after the first allocation of course). This is mostly relevant for the
* `YaProcessData` object stored inside of `YaAudioProcessor::Process`.
* These buffers are thread local and will also never shrink, but that
* should not be an issue with the `IAudioProcessor` and `IComponent`
* functions. Saving and loading state is handled on the main sockets,
* which don't use these persistent buffers.
*
* @relates Vst3MessageHandler::send_event
*/
@@ -203,6 +207,13 @@ class Vst3MessageHandler : public AdHocSocketHandler<Thread> {
void receive_messages(std::optional<std::pair<Vst3Logger&, bool>> logging,
F callback) {
thread_local std::vector<uint8_t> 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<Request> persistent_object =
persistent_buffers ? std::make_optional<Request>() : std::nullopt;
// Reading, processing, and writing back the response for the requests
// we receive works in the same way regardless of which socket we're
@@ -211,7 +222,8 @@ class Vst3MessageHandler : public AdHocSocketHandler<Thread> {
[&](boost::asio::local::stream_protocol::socket& socket) {
auto request =
persistent_buffers
? read_object<Request>(socket, persistent_buffer)
? read_object<Request>(socket, *persistent_object,
persistent_buffer)
: read_object<Request>(socket);
// See the comment in `receive_into()` for more information