Skip to content

Commit

Permalink
PERF: Make ImageRegion trivially copyable, remove Region inheritance
Browse files Browse the repository at this point in the history
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<itk::ImageRegion<2>[]>(n)`.
  • Loading branch information
N-Dekker committed Nov 22, 2023
1 parent 9f3d9a4 commit 7fead70
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 11 deletions.
25 changes: 16 additions & 9 deletions Modules/Core/Common/include/itkImageRegion.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,18 @@ class ITK_TEMPLATE_EXPORT ImageBase;
* \endsphinx
*/
template <unsigned int VImageDimension>
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;
Expand Down Expand Up @@ -106,20 +109,24 @@ class ITK_TEMPLATE_EXPORT ImageRegion final : public Region
using SliceRegion = ImageRegion<Self::SliceDimension>;

/** 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). */
ImageRegion() noexcept = default;

/** 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. */
Expand Down Expand Up @@ -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 } };
Expand Down
10 changes: 8 additions & 2 deletions Modules/Core/Common/include/itkImageRegion.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,16 @@ ImageRegion<VImageDimension>::GetNumberOfPixels() const -> SizeValueType

template <unsigned int VImageDimension>
void
ImageRegion<VImageDimension>::PrintSelf(std::ostream & os, Indent indent) const
ImageRegion<VImageDimension>::Print(std::ostream & os, Indent indent) const
{
Superclass::PrintSelf(os, indent);
os << indent << this->GetNameOfClass() << " (" << this << ")\n";
this->PrintSelf(os, indent.GetNextIndent());
}

template <unsigned int VImageDimension>
void
ImageRegion<VImageDimension>::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;
Expand Down
6 changes: 6 additions & 0 deletions Modules/Core/Common/test/itkImageRegionTest.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@
*=========================================================================*/

#include <iostream>
#include <type_traits> // For is_trivially_copyable_v.
#include "itkImageRegion.h"
#include "itkFloatingPointExceptions.h"


static_assert(std::is_trivially_copyable_v<itk::ImageRegion<2>> && std::is_trivially_copyable_v<itk::ImageRegion<3>>,
"ImageRegion<VImageDimension> should be trivially copyable.");


int
itkImageRegionTest(int, char *[])
{
Expand Down

0 comments on commit 7fead70

Please sign in to comment.