[common/logging] faster logging by avoiding constructing unused strings/results (and filtering first) (#2603)
basically std::string would be invoked even when the logging was filtered, then destroyed instantly, invoking malloc/free and polluting mem arenas for no good reason Signed-off-by: lizzie <lizzie@eden-emu.dev> Reviewed-on: #2603 Reviewed-by: MaranBr <maranbr@eden-emu.dev> Reviewed-by: crueter <crueter@eden-emu.dev> Co-authored-by: lizzie <lizzie@eden-emu.dev> Co-committed-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
parent
61adc85c4b
commit
76b5d6778e
4 changed files with 45 additions and 45 deletions
|
@ -39,9 +39,17 @@ namespace Common::Log {
|
|||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* Interface for logging backends.
|
||||
*/
|
||||
/// @brief Trims up to and including the last of ../, ..\, src/, src\ in a string
|
||||
/// do not be fooled this isn't generating new strings on .rodata :)
|
||||
constexpr const char* TrimSourcePath(std::string_view source) {
|
||||
const auto rfind = [source](const std::string_view match) {
|
||||
return source.rfind(match) == source.npos ? 0 : (source.rfind(match) + match.size());
|
||||
};
|
||||
auto idx = (std::max)({rfind("src/"), rfind("src\\"), rfind("../"), rfind("..\\")});
|
||||
return source.data() + idx;
|
||||
}
|
||||
|
||||
/// @brief Interface for logging backends.
|
||||
class Backend {
|
||||
public:
|
||||
virtual ~Backend() = default;
|
||||
|
@ -53,9 +61,7 @@ public:
|
|||
virtual void Flush() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Backend that writes to stderr and with color
|
||||
*/
|
||||
/// @brief Backend that writes to stderr and with color
|
||||
class ColorConsoleBackend final : public Backend {
|
||||
public:
|
||||
explicit ColorConsoleBackend() = default;
|
||||
|
@ -84,9 +90,7 @@ private:
|
|||
std::atomic_bool enabled{false};
|
||||
};
|
||||
|
||||
/**
|
||||
* Backend that writes to a file passed into the constructor
|
||||
*/
|
||||
/// @brief Backend that writes to a file passed into the constructor
|
||||
class FileBackend final : public Backend {
|
||||
public:
|
||||
explicit FileBackend(const std::filesystem::path& filename) {
|
||||
|
@ -248,13 +252,14 @@ public:
|
|||
color_console_backend.SetEnabled(enabled);
|
||||
}
|
||||
|
||||
bool CanPushEntry(Class log_class, Level log_level) const noexcept {
|
||||
return filter.CheckMessage(log_class, log_level);
|
||||
}
|
||||
|
||||
void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num,
|
||||
const char* function, std::string&& message) {
|
||||
if (!filter.CheckMessage(log_class, log_level)) {
|
||||
return;
|
||||
}
|
||||
const char* function, std::string&& message) noexcept {
|
||||
message_queue.EmplaceWait(
|
||||
CreateEntry(log_class, log_level, filename, line_num, function, std::move(message)));
|
||||
CreateEntry(log_class, log_level, TrimSourcePath(filename), line_num, function, std::move(message)));
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -368,8 +373,9 @@ void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
|
|||
unsigned int line_num, const char* function, fmt::string_view format,
|
||||
const fmt::format_args& args) {
|
||||
if (!initialization_in_progress_suppress_logging) {
|
||||
Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function,
|
||||
fmt::vformat(format, args));
|
||||
auto& instance = Impl::Instance();
|
||||
if (instance.CanPushEntry(log_class, log_level))
|
||||
instance.PushEntry(log_class, log_level, filename, line_num, function, fmt::vformat(format, args));
|
||||
}
|
||||
}
|
||||
} // namespace Common::Log
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
@ -9,22 +12,20 @@ namespace Common::Log {
|
|||
namespace {
|
||||
template <typename It>
|
||||
Level GetLevelByName(const It begin, const It end) {
|
||||
for (u8 i = 0; i < static_cast<u8>(Level::Count); ++i) {
|
||||
const char* level_name = GetLevelName(static_cast<Level>(i));
|
||||
if (Common::ComparePartialString(begin, end, level_name)) {
|
||||
return static_cast<Level>(i);
|
||||
}
|
||||
for (u32 i = 0; i < u32(Level::Count); ++i) {
|
||||
const char* level_name = GetLevelName(Level(i));
|
||||
if (Common::ComparePartialString(begin, end, level_name))
|
||||
return Level(i);
|
||||
}
|
||||
return Level::Count;
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
Class GetClassByName(const It begin, const It end) {
|
||||
for (u8 i = 0; i < static_cast<u8>(Class::Count); ++i) {
|
||||
const char* level_name = GetLogClassName(static_cast<Class>(i));
|
||||
if (Common::ComparePartialString(begin, end, level_name)) {
|
||||
return static_cast<Class>(i);
|
||||
}
|
||||
for (u32 i = 0; i < u32(Class::Count); ++i) {
|
||||
const char* level_name = GetLogClassName(Class(i));
|
||||
if (Common::ComparePartialString(begin, end, level_name))
|
||||
return Class(i);
|
||||
}
|
||||
return Class::Count;
|
||||
}
|
||||
|
@ -229,13 +230,12 @@ void Filter::ParseFilterString(std::string_view filter_view) {
|
|||
}
|
||||
|
||||
bool Filter::CheckMessage(Class log_class, Level level) const {
|
||||
return static_cast<u8>(level) >=
|
||||
static_cast<u8>(class_levels[static_cast<std::size_t>(log_class)]);
|
||||
return u8(level) >= u8(class_levels[std::size_t(log_class)]);
|
||||
}
|
||||
|
||||
bool Filter::IsDebug() const {
|
||||
return std::any_of(class_levels.begin(), class_levels.end(), [](const Level& l) {
|
||||
return static_cast<u8>(l) <= static_cast<u8>(Level::Debug);
|
||||
return u8(l) <= u8(Level::Debug);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -16,15 +16,6 @@
|
|||
|
||||
namespace Common::Log {
|
||||
|
||||
// trims up to and including the last of ../, ..\, src/, src\ in a string
|
||||
constexpr const char* TrimSourcePath(std::string_view source) {
|
||||
const auto rfind = [source](const std::string_view match) {
|
||||
return source.rfind(match) == source.npos ? 0 : (source.rfind(match) + match.size());
|
||||
};
|
||||
auto idx = (std::max)({rfind("src/"), rfind("src\\"), rfind("../"), rfind("..\\")});
|
||||
return source.data() + idx;
|
||||
}
|
||||
|
||||
/// Logs a message to the global logger, using fmt
|
||||
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
|
||||
unsigned int line_num, const char* function, fmt::string_view format,
|
||||
|
@ -42,7 +33,7 @@ void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsig
|
|||
#ifdef _DEBUG
|
||||
#define LOG_TRACE(log_class, ...) \
|
||||
Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Trace, \
|
||||
Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \
|
||||
__FILE__, __LINE__, __func__, \
|
||||
__VA_ARGS__)
|
||||
#else
|
||||
#define LOG_TRACE(log_class, fmt, ...) (void(0))
|
||||
|
@ -50,21 +41,21 @@ void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsig
|
|||
|
||||
#define LOG_DEBUG(log_class, ...) \
|
||||
Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Debug, \
|
||||
Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \
|
||||
__FILE__, __LINE__, __func__, \
|
||||
__VA_ARGS__)
|
||||
#define LOG_INFO(log_class, ...) \
|
||||
Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Info, \
|
||||
Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \
|
||||
__FILE__, __LINE__, __func__, \
|
||||
__VA_ARGS__)
|
||||
#define LOG_WARNING(log_class, ...) \
|
||||
Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Warning, \
|
||||
Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \
|
||||
__FILE__, __LINE__, __func__, \
|
||||
__VA_ARGS__)
|
||||
#define LOG_ERROR(log_class, ...) \
|
||||
Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Error, \
|
||||
Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \
|
||||
__FILE__, __LINE__, __func__, \
|
||||
__VA_ARGS__)
|
||||
#define LOG_CRITICAL(log_class, ...) \
|
||||
Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Critical, \
|
||||
Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \
|
||||
__FILE__, __LINE__, __func__, \
|
||||
__VA_ARGS__)
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
@ -286,7 +289,7 @@ Result CheckOpenSSLErrors() {
|
|||
msg.append(data);
|
||||
}
|
||||
Common::Log::FmtLogMessage(Common::Log::Class::Service_SSL, Common::Log::Level::Error,
|
||||
Common::Log::TrimSourcePath(file), line, func, "OpenSSL: {}",
|
||||
file, line, func, "OpenSSL: {}",
|
||||
msg);
|
||||
}
|
||||
return ResultInternalError;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue