From d73f19acb95d164ab8ce963d2c50354f9344cae1 Mon Sep 17 00:00:00 2001 From: Niels Dekker Date: Mon, 20 Nov 2023 17:05:47 +0100 Subject: [PATCH] PERF: Make `ImageRegion` trivially copyable, remove `Region` inheritance Made `ImageRegion` more lightweight, by declaring all of its member functions non-virtual, and by removing its inheritance from `Region`. The size of `ImageRegion<2>` was observed to go down from 40 bytes (before this commit) to 32 bytes (after this commit), on Visual C++ 2022 (x64). A run-time performance improvement of more than 25% on default-constructing and destructing a sequence of `ImageRegion` objects was observed, by benchmarking `std::make_unique[]>(n)`. --- Modules/Core/Common/include/itkImageRegion.h | 25 ++++++++++++------- .../Core/Common/include/itkImageRegion.hxx | 10 ++++++-- .../Core/Common/test/itkImageRegionTest.cxx | 6 +++++ 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/Modules/Core/Common/include/itkImageRegion.h b/Modules/Core/Common/include/itkImageRegion.h index 8045eb42fc91..335fffa68db3 100644 --- a/Modules/Core/Common/include/itkImageRegion.h +++ b/Modules/Core/Common/include/itkImageRegion.h @@ -66,15 +66,18 @@ class ITK_TEMPLATE_EXPORT ImageBase; * \endsphinx */ template -class ITK_TEMPLATE_EXPORT ImageRegion final : public Region +class ITK_TEMPLATE_EXPORT ImageRegion final { public: /** Standard class type aliases. */ using Self = ImageRegion; - using Superclass = Region; - /** Standard part of all itk objects. */ - itkTypeMacro(ImageRegion, Region); + /** Standard part of all itk objects, but non-virtual. */ + const char * + GetNameOfClass() const + { + return "ImageRegion"; + } /** Dimension of the image available at compile time. */ static constexpr unsigned int ImageDimension = VImageDimension; @@ -106,12 +109,16 @@ class ITK_TEMPLATE_EXPORT ImageRegion final : public Region using SliceRegion = ImageRegion; /** Return the region type. Images are described with structured regions. */ - Superclass::RegionEnum - GetRegionType() const override + Region::RegionEnum + GetRegionType() const { - return Superclass::RegionEnum::ITK_STRUCTURED_REGION; + return Region::RegionEnum::ITK_STRUCTURED_REGION; } + /** Print the region. */ + void + Print(std::ostream & os, Indent indent = 0) const; + /** Constructor. ImageRegion is a lightweight object that is not reference * counted, so the constructor is public. Its two data members are filled * with zeros (using C++11 default member initializers). */ @@ -119,7 +126,7 @@ class ITK_TEMPLATE_EXPORT ImageRegion final : public Region /** Destructor. ImageRegion is a lightweight object that is not reference * counted, so the destructor is public. */ - ~ImageRegion() override = default; + ~ImageRegion() = default; /** Copy constructor. ImageRegion is a lightweight object that is not * reference counted, so the copy constructor is public. */ @@ -339,7 +346,7 @@ class ITK_TEMPLATE_EXPORT ImageRegion final : public Region * instead) but used in the hierarchical print process to combine the * output of several classes. */ void - PrintSelf(std::ostream & os, Indent indent) const override; + PrintSelf(std::ostream & os, Indent indent) const; private: IndexType m_Index = { { 0 } }; diff --git a/Modules/Core/Common/include/itkImageRegion.hxx b/Modules/Core/Common/include/itkImageRegion.hxx index 6385cd615e24..fd8d9838c25e 100644 --- a/Modules/Core/Common/include/itkImageRegion.hxx +++ b/Modules/Core/Common/include/itkImageRegion.hxx @@ -84,10 +84,16 @@ ImageRegion::GetNumberOfPixels() const -> SizeValueType template void -ImageRegion::PrintSelf(std::ostream & os, Indent indent) const +ImageRegion::Print(std::ostream & os, Indent indent) const { - Superclass::PrintSelf(os, indent); + os << indent << this->GetNameOfClass() << " (" << this << ")\n"; + this->PrintSelf(os, indent.GetNextIndent()); +} +template +void +ImageRegion::PrintSelf(std::ostream & os, Indent indent) const +{ os << indent << "Dimension: " << this->GetImageDimension() << std::endl; os << indent << "Index: " << m_Index << std::endl; os << indent << "Size: " << m_Size << std::endl; diff --git a/Modules/Core/Common/test/itkImageRegionTest.cxx b/Modules/Core/Common/test/itkImageRegionTest.cxx index c75b1f748b90..7b13008c9885 100644 --- a/Modules/Core/Common/test/itkImageRegionTest.cxx +++ b/Modules/Core/Common/test/itkImageRegionTest.cxx @@ -17,9 +17,15 @@ *=========================================================================*/ #include +#include // For is_trivially_copyable_v. #include "itkImageRegion.h" #include "itkFloatingPointExceptions.h" + +static_assert(std::is_trivially_copyable_v> && std::is_trivially_copyable_v>, + "ImageRegion should be trivially copyable."); + + int itkImageRegionTest(int, char *[]) {