Skip to content

Commit

Permalink
improve performance of span_iterator w/ clang
Browse files Browse the repository at this point in the history
Issue: microsoft#1165

Before this PR, the range-for loop was ~3300x slower. After this PR, it
is ~1.005x slower

The clang optimizer is very good at optimizing `current != end`, so
we changed to this idiom. This moves the Expects assertion into the
constructor instead of on the hot-path which is called whenever either
operator++ or operator* is called.

Note: The codegen for the assertion is still a missed optimization,
but less worrisome as it only happens once per iterator.

Note: benchmarks on M1 Macbook Pro w/ Apple Clang 16.0.0
  • Loading branch information
carsonRadtke committed Nov 9, 2024
1 parent 87f9d76 commit 898db79
Showing 1 changed file with 8 additions and 11 deletions.
19 changes: 8 additions & 11 deletions include/gsl/span
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,10 @@ namespace details

constexpr span_iterator(pointer begin, pointer end, pointer current)
: begin_(begin), end_(end), current_(current)
{}
{
Expects(begin && current && end);
Expects(begin <= current && current <= end);
}

constexpr operator span_iterator<const Type>() const noexcept
{
Expand All @@ -149,21 +152,18 @@ namespace details

constexpr reference operator*() const noexcept
{
Expects(begin_ && end_);
Expects(begin_ <= current_ && current_ < end_);
Expects(current_ != end_);
return *current_;
}

constexpr pointer operator->() const noexcept
{
Expects(begin_ && end_);
Expects(begin_ <= current_ && current_ < end_);
Expects(current_ != end_);
return current_;
}
constexpr span_iterator& operator++() noexcept
{
Expects(begin_ && current_ && end_);
Expects(current_ < end_);
Expects(current_ != end_);
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
Expand All @@ -180,8 +180,7 @@ namespace details

constexpr span_iterator& operator--() noexcept
{
Expects(begin_ && end_);
Expects(begin_ < current_);
Expects(begin != current_);
--current_;
return *this;
}
Expand All @@ -195,7 +194,6 @@ namespace details

constexpr span_iterator& operator+=(const difference_type n) noexcept
{
if (n != 0) Expects(begin_ && current_ && end_);
if (n > 0) Expects(end_ - current_ >= n);
if (n < 0) Expects(current_ - begin_ >= -n);
// clang-format off
Expand All @@ -220,7 +218,6 @@ namespace details

constexpr span_iterator& operator-=(const difference_type n) noexcept
{
if (n != 0) Expects(begin_ && current_ && end_);
if (n > 0) Expects(current_ - begin_ >= n);
if (n < 0) Expects(end_ - current_ >= -n);
GSL_SUPPRESS(bounds .1)
Expand Down

0 comments on commit 898db79

Please sign in to comment.