Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/src/catch2
diff options
context:
space:
mode:
authorMartin Hořeňovský2023-01-27 22:12:57 +0100
committerMartin Hořeňovský2023-01-29 10:14:20 +0100
commit43f02027e47310e200f20f5c3a1de6fe281e2f81 (patch)
treed0a0f722915ee180eaed42d6d4fac553f758cee1 /src/catch2
parent906552f8c831d0dd1917484b53dd080537f19acd (diff)
downloadcatch3-43f02027e47310e200f20f5c3a1de6fe281e2f81.tar.gz
Avoid allocations when looking for trackers
Now we delay allocating owning `NameAndLocation` instances until we construct a new tracker (because a tracker's lifetime can be significantly different from the underlying tracked-thing's name). This saves 4239 allocations (436948 -> 432709) when running `./tests/SelfTest -o /dev/null`, at some cost to code clarity due to introducing a new ref type, `NameAndLocationRef`.
Diffstat (limited to 'src/catch2')
-rw-r--r--src/catch2/internal/catch_run_context.cpp17
-rw-r--r--src/catch2/internal/catch_test_case_tracker.cpp49
-rw-r--r--src/catch2/internal/catch_test_case_tracker.hpp40
3 files changed, 69 insertions, 37 deletions
diff --git a/src/catch2/internal/catch_run_context.cpp b/src/catch2/internal/catch_run_context.cpp
index 506dc5c9..e0b5ccaa 100644
--- a/src/catch2/internal/catch_run_context.cpp
+++ b/src/catch2/internal/catch_run_context.cpp
@@ -29,12 +29,12 @@ namespace Catch {
struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
GeneratorBasePtr m_generator;
- GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
- : TrackerBase( nameAndLocation, ctx, parent )
+ GeneratorTracker( TestCaseTracking::NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent )
+ : TrackerBase( CATCH_MOVE(nameAndLocation), ctx, parent )
{}
~GeneratorTracker() override;
- static GeneratorTracker* acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) {
+ static GeneratorTracker* acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocationRef nameAndLocation ) {
GeneratorTracker* tracker;
ITracker& currentTracker = ctx.currentTracker();
@@ -226,7 +226,7 @@ namespace Catch {
uint64_t testRuns = 0;
do {
m_trackerContext.startCycle();
- m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo));
+ m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocationRef(testInfo.name, testInfo.lineInfo));
m_reporter->testCasePartialStarting(testInfo, testRuns);
@@ -298,7 +298,8 @@ namespace Catch {
}
bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) {
- ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo));
+ ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocationRef(sectionInfo.name, sectionInfo.lineInfo));
+
if (!sectionTracker.isOpen())
return false;
m_activeSections.push_back(&sectionTracker);
@@ -317,8 +318,8 @@ namespace Catch {
using namespace Generators;
GeneratorTracker* tracker = GeneratorTracker::acquire(
m_trackerContext,
- TestCaseTracking::NameAndLocation(
- static_cast<std::string>( generatorName ), lineInfo ) );
+ TestCaseTracking::NameAndLocationRef(
+ generatorName, lineInfo ) );
m_lastAssertionInfo.lineInfo = lineInfo;
return tracker;
}
@@ -335,7 +336,7 @@ namespace Catch {
"Trying to create tracker for a genreator that already has one" );
auto newTracker = Catch::Detail::make_unique<Generators::GeneratorTracker>(
- nameAndLoc, m_trackerContext, &currentTracker );
+ CATCH_MOVE(nameAndLoc), m_trackerContext, &currentTracker );
auto ret = newTracker.get();
currentTracker.addChild( CATCH_MOVE( newTracker ) );
diff --git a/src/catch2/internal/catch_test_case_tracker.cpp b/src/catch2/internal/catch_test_case_tracker.cpp
index e230fac1..cd0990b5 100644
--- a/src/catch2/internal/catch_test_case_tracker.cpp
+++ b/src/catch2/internal/catch_test_case_tracker.cpp
@@ -22,8 +22,8 @@
namespace Catch {
namespace TestCaseTracking {
- NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location )
- : name( _name ),
+ NameAndLocation::NameAndLocation( std::string&& _name, SourceLineInfo const& _location )
+ : name( CATCH_MOVE(_name) ),
location( _location )
{}
@@ -38,14 +38,12 @@ namespace TestCaseTracking {
m_children.push_back( CATCH_MOVE(child) );
}
- ITracker* ITracker::findChild( NameAndLocation const& nameAndLocation ) {
+ ITracker* ITracker::findChild( NameAndLocationRef nameAndLocation ) {
auto it = std::find_if(
m_children.begin(),
m_children.end(),
[&nameAndLocation]( ITrackerPtr const& tracker ) {
- return tracker->nameAndLocation().location ==
- nameAndLocation.location &&
- tracker->nameAndLocation().name == nameAndLocation.name;
+ return tracker->nameAndLocation() == nameAndLocation;
} );
return ( it != m_children.end() ) ? it->get() : nullptr;
}
@@ -108,8 +106,8 @@ namespace TestCaseTracking {
}
- TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ):
- ITracker(nameAndLocation, parent),
+ TrackerBase::TrackerBase( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent ):
+ ITracker(CATCH_MOVE(nameAndLocation), parent),
m_ctx( ctx )
{}
@@ -169,13 +167,14 @@ namespace TestCaseTracking {
m_ctx.setCurrentTracker( this );
}
- SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
- : TrackerBase( nameAndLocation, ctx, parent ),
- m_trimmed_name(trim(nameAndLocation.name))
+ SectionTracker::SectionTracker( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent )
+ : TrackerBase( CATCH_MOVE(nameAndLocation), ctx, parent ),
+ m_trimmed_name(trim(ITracker::nameAndLocation().name))
{
if( parent ) {
- while( !parent->isSectionTracker() )
+ while ( !parent->isSectionTracker() ) {
parent = parent->parent();
+ }
SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
addNextFilters( parentSection.m_filters );
@@ -195,24 +194,30 @@ namespace TestCaseTracking {
bool SectionTracker::isSectionTracker() const { return true; }
- SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
- SectionTracker* section;
+ SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocationRef nameAndLocation ) {
+ SectionTracker* tracker;
ITracker& currentTracker = ctx.currentTracker();
if ( ITracker* childTracker =
currentTracker.findChild( nameAndLocation ) ) {
assert( childTracker );
assert( childTracker->isSectionTracker() );
- section = static_cast<SectionTracker*>( childTracker );
+ tracker = static_cast<SectionTracker*>( childTracker );
} else {
- auto newSection = Catch::Detail::make_unique<SectionTracker>(
- nameAndLocation, ctx, &currentTracker );
- section = newSection.get();
- currentTracker.addChild( CATCH_MOVE( newSection ) );
+ auto newTracker = Catch::Detail::make_unique<SectionTracker>(
+ NameAndLocation{ static_cast<std::string>(nameAndLocation.name),
+ nameAndLocation.location },
+ ctx,
+ &currentTracker );
+ tracker = newTracker.get();
+ currentTracker.addChild( CATCH_MOVE( newTracker ) );
+ }
+
+ if ( !ctx.completedCycle() ) {
+ tracker->tryOpen();
}
- if( !ctx.completedCycle() )
- section->tryOpen();
- return *section;
+
+ return *tracker;
}
void SectionTracker::tryOpen() {
diff --git a/src/catch2/internal/catch_test_case_tracker.hpp b/src/catch2/internal/catch_test_case_tracker.hpp
index 1e31e425..0021d254 100644
--- a/src/catch2/internal/catch_test_case_tracker.hpp
+++ b/src/catch2/internal/catch_test_case_tracker.hpp
@@ -22,7 +22,7 @@ namespace TestCaseTracking {
std::string name;
SourceLineInfo location;
- NameAndLocation( std::string const& _name, SourceLineInfo const& _location );
+ NameAndLocation( std::string&& _name, SourceLineInfo const& _location );
friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) {
return lhs.name == rhs.name
&& lhs.location == rhs.location;
@@ -33,6 +33,32 @@ namespace TestCaseTracking {
}
};
+ /**
+ * This is a variant of `NameAndLocation` that does not own the name string
+ *
+ * This avoids extra allocations when trying to locate a tracker by its
+ * name and location, as long as we make sure that trackers only keep
+ * around the owning variant.
+ */
+ struct NameAndLocationRef {
+ StringRef name;
+ SourceLineInfo location;
+
+ constexpr NameAndLocationRef( StringRef name_,
+ SourceLineInfo location_ ):
+ name( name_ ), location( location_ ) {}
+
+ friend bool operator==( NameAndLocation const& lhs,
+ NameAndLocationRef rhs ) {
+ return StringRef( lhs.name ) == rhs.name &&
+ lhs.location == rhs.location;
+ }
+ friend bool operator==( NameAndLocationRef lhs,
+ NameAndLocation const& rhs ) {
+ return rhs == lhs;
+ }
+ };
+
class ITracker;
using ITrackerPtr = Catch::Detail::unique_ptr<ITracker>;
@@ -57,8 +83,8 @@ namespace TestCaseTracking {
CycleState m_runState = NotStarted;
public:
- ITracker( NameAndLocation const& nameAndLoc, ITracker* parent ):
- m_nameAndLocation( nameAndLoc ),
+ ITracker( NameAndLocation&& nameAndLoc, ITracker* parent ):
+ m_nameAndLocation( CATCH_MOVE(nameAndLoc) ),
m_parent( parent )
{}
@@ -97,7 +123,7 @@ namespace TestCaseTracking {
*
* Returns nullptr if not found.
*/
- ITracker* findChild( NameAndLocation const& nameAndLocation );
+ ITracker* findChild( NameAndLocationRef nameAndLocation );
//! Have any children been added?
bool hasChildren() const {
return !m_children.empty();
@@ -154,7 +180,7 @@ namespace TestCaseTracking {
TrackerContext& m_ctx;
public:
- TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
+ TrackerBase( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent );
bool isComplete() const override;
@@ -172,13 +198,13 @@ namespace TestCaseTracking {
std::vector<StringRef> m_filters;
std::string m_trimmed_name;
public:
- SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
+ SectionTracker( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent );
bool isSectionTracker() const override;
bool isComplete() const override;
- static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation );
+ static SectionTracker& acquire( TrackerContext& ctx, NameAndLocationRef nameAndLocation );
void tryOpen();