From 5aa8d113215bd9a97ecc1a2f3fc9506947a2fa57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 21 Jul 2025 19:45:43 +0200 Subject: [PATCH] Clear unscoped messages lazily This improves the fast path performance for successful assertions by about 7%, at the cost of potentially keeping around the message allocation longer. --- src/catch2/internal/catch_run_context.cpp | 8 ++++++-- src/catch2/internal/catch_run_context.hpp | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/catch2/internal/catch_run_context.cpp b/src/catch2/internal/catch_run_context.cpp index 118d37f8..dca16618 100644 --- a/src/catch2/internal/catch_run_context.cpp +++ b/src/catch2/internal/catch_run_context.cpp @@ -296,6 +296,10 @@ namespace Catch { } { + if ( m_clearMessageScopes ) { + m_messageScopes.clear(); + m_clearMessageScopes = false; + } auto _ = scopedDeactivate( *m_outputRedirect ); m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ); } @@ -524,9 +528,9 @@ namespace Catch { void RunContext::assertionPassedFastPath(SourceLineInfo lineInfo) { m_lastKnownLineInfo = lineInfo; - m_lastAssertionPassed = true; ++m_totals.assertions.passed; - m_messageScopes.clear(); + m_lastAssertionPassed = true; + m_clearMessageScopes = true; } bool RunContext::aborting() const { diff --git a/src/catch2/internal/catch_run_context.hpp b/src/catch2/internal/catch_run_context.hpp index 6e9f21f7..c8cc974a 100644 --- a/src/catch2/internal/catch_run_context.hpp +++ b/src/catch2/internal/catch_run_context.hpp @@ -148,7 +148,8 @@ namespace Catch { Totals m_totals; IEventListenerPtr m_reporter; std::vector m_messages; - std::vector m_messageScopes; /* Keeps owners of so-called unscoped messages. */ + // Owners for the UNSCOPED_X information macro + std::vector m_messageScopes; SourceLineInfo m_lastKnownLineInfo; std::vector m_unfinishedSections; std::vector m_activeSections; @@ -158,6 +159,9 @@ namespace Catch { // Caches m_config->abortAfter() to avoid vptr calls/allow inlining size_t m_abortAfterXFailedAssertions; bool m_lastAssertionPassed = false; + // Should we clear message scopes before sending off the messages to reporter? + // Set in `assertionPassedFastPath` to avoid doing the full clear there. + bool m_clearMessageScopes = false; bool m_shouldReportUnexpected = true; // Caches whether `assertionStarting` events should be sent to the reporter. bool m_reportAssertionStarting;