From df93944f3b96d98883574562bb28d3d0a91492b0 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Sun, 23 May 2021 00:21:21 +0200 Subject: [PATCH] Prevent allocations caused by Logger::log_trace C++ would always construct an `std::string` from the string constant every iteration. Since this also happened when `YABRIDGE_DEBUG_LEVEL` is not set to 2, this ended up causing unnecessary allocations. --- CHANGELOG.md | 2 ++ src/common/logging/common.cpp | 6 ------ src/common/logging/common.h | 26 ++++++++++++++++---------- src/common/logging/vst2.h | 15 ++++++++------- src/common/logging/vst3.h | 15 ++++++++------- src/plugin/bridges/vst2.cpp | 12 ++++++------ 6 files changed, 40 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index faaa52e1..16f38c5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,8 @@ Versioning](https://semver.org/spec/v2.0.0.html). visible. - Fixed _Voxengo_ VST2 plugins in **Renoise** freezing when loading a project or when otherwise restoring plugin state. +- Fixed logging traces in the VST2 audio processing functions causing + allocations even when `YABRIDGE_DEBUG_LEVEL` is not set to 2. - Fixed builds on Wine 6.8 because of internal changes to Wine's `windows.h` implementation. diff --git a/src/common/logging/common.cpp b/src/common/logging/common.cpp index c251c90b..cd0a86b0 100644 --- a/src/common/logging/common.cpp +++ b/src/common/logging/common.cpp @@ -125,9 +125,3 @@ void Logger::log(const std::string& message) { *stream << formatted_message.str() << std::flush; } - -void Logger::log_trace(const std::string& message) { - if (verbosity >= Verbosity::all_events) { - log(message); - } -} diff --git a/src/common/logging/common.h b/src/common/logging/common.h index 2b9e8888..ea4ec057 100644 --- a/src/common/logging/common.h +++ b/src/common/logging/common.h @@ -28,6 +28,8 @@ #include #include +#include "../utils.h" + /** * Boost 1.72 was released with a known breaking bug caused by a missing * typedef: https://github.com/boostorg/process/issues/116. @@ -132,16 +134,6 @@ class Logger { */ void log(const std::string& message); - /** - * Log a message that should only be printed when the `verbosity` is set to - * `all_events`. This should only be used for simple primitive messages - * without any formatting since the actual check happens within this - * function. - * - * @param message The message to write. - */ - void log_trace(const std::string& message); - /** * Write output from an async pipe to the log on a line by line basis. * Useful for logging the Wine process's STDOUT and STDERR streams. @@ -172,6 +164,20 @@ class Logger { }); } + /** + * Log a message that should only be printed when the `verbosity` is set to + * `all_events`. This uses a lambda since producing a string always + * allocates. + * + * @param message A lambda producing a string that should be written. + */ + template F> + void log_trace(F&& fn) { + if (verbosity >= Verbosity::all_events) { + log(fn()); + } + } + /** * The verbosity level of this logger instance. Based on this certain * messages may or may not be shown. diff --git a/src/common/logging/vst2.h b/src/common/logging/vst2.h index 9732b726..4f670778 100644 --- a/src/common/logging/vst2.h +++ b/src/common/logging/vst2.h @@ -46,13 +46,6 @@ class Vst2Logger { */ inline void log(const std::string& message) { logger.log(message); } - /** - * @see Logger::log_trace - */ - inline void log_trace(const std::string& message) { - logger.log_trace(message); - } - // The following functions are for logging specific events, they are only // enabled for verbosity levels higher than 1 (i.e. `Verbosity::events`) void log_get_parameter(int index); @@ -77,6 +70,14 @@ class Vst2Logger { const std::optional& value_payload, bool from_cache = false); + /** + * @see Logger::log_trace + */ + template F> + inline void log_trace(F&& fn) { + logger.log_trace(std::forward(fn)); + } + /** * The underlying logger instance we're wrapping. */ diff --git a/src/common/logging/vst3.h b/src/common/logging/vst3.h index 8e184342..b452a5a9 100644 --- a/src/common/logging/vst3.h +++ b/src/common/logging/vst3.h @@ -35,13 +35,6 @@ class Vst3Logger { */ inline void log(const std::string& message) { logger.log(message); } - /** - * @see Logger::log_trace - */ - inline void log_trace(const std::string& message) { - logger.log_trace(message); - } - /** * Log calls to `FUnknown::queryInterface`. This will separately log about * successful queries, queries for interfaces the object did not implement, @@ -340,6 +333,14 @@ class Vst3Logger { }); } + /** + * @see Logger::log_trace + */ + template F> + inline void log_trace(F&& fn) { + logger.log_trace(std::forward(fn)); + } + Logger& logger; private: diff --git a/src/plugin/bridges/vst2.cpp b/src/plugin/bridges/vst2.cpp index ebeb7fdf..6bd59b41 100644 --- a/src/plugin/bridges/vst2.cpp +++ b/src/plugin/bridges/vst2.cpp @@ -663,27 +663,27 @@ void Vst2PluginBridge::process(AEffect* /*plugin*/, // Technically either `Vst2PluginBridge::process()` or // `Vst2PluginBridge::process_replacing()` could actually call the other // function on the plugin depending on what the plugin supports. - logger.log_trace(">> process() :: start"); + logger.log_trace([]() { return ">> process() :: start"; }); do_process(inputs, outputs, sample_frames); - logger.log_trace(" process() :: end"); + logger.log_trace([]() { return " process() :: end"; }); } void Vst2PluginBridge::process_replacing(AEffect* /*plugin*/, float** inputs, float** outputs, int sample_frames) { - logger.log_trace(">> processReplacing() :: start"); + logger.log_trace([]() { return ">> processReplacing() :: start"; }); do_process(inputs, outputs, sample_frames); - logger.log_trace(" processReplacing() :: end"); + logger.log_trace([]() { return " processReplacing() :: end"; }); } void Vst2PluginBridge::process_double_replacing(AEffect* /*plugin*/, double** inputs, double** outputs, int sample_frames) { - logger.log_trace(">> processDoubleReplacing() :: start"); + logger.log_trace([]() { return ">> processDoubleReplacing() :: start"; }); do_process(inputs, outputs, sample_frames); - logger.log_trace(" processDoubleReplacing() :: end"); + logger.log_trace([]() { return " processDoubleReplacing() :: end"; }); } float Vst2PluginBridge::get_parameter(AEffect* /*plugin*/, int index) {