Skip to content

Commit 5f6b814

Browse files
authored
Improve performance of til::equals (#19653)
As explained in the added comment. Perf 📈.
1 parent e707c10 commit 5f6b814

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

src/inc/til/string.h

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -159,16 +159,29 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
159159

160160
// Just like std::wstring_view::operator==().
161161
//
162-
// At the time of writing wmemcmp() is not an intrinsic for MSVC,
163-
// but the STL uses it to implement wide string comparisons.
164-
// This produces 3x the assembly _per_ comparison and increases
165-
// runtime by 2-3x for strings of medium length (16 characters)
166-
// and 5x or more for long strings (128 characters or more).
162+
// NOTE: If you pass a literal, ALWAYS pass it as the 2nd argument.
163+
// This is because MSVC does not understand that `lhs.size() == rhs.size()` implies
164+
// that a constant size on one side implies a constant size on the other side.
165+
// As such the size argument to memcmp() must be the constant size, which is `rhs`.
166+
//
167+
// The STL uses wmemcmp() to implement wide string comparisons.
168+
// Compared to memcmp() this results 3x the assembly per comparison,
169+
// while running 2-3x slower for 16 chars and >5x slower for >128 chars.
167170
// See: https://github.com/microsoft/STL/issues/2289
168171
template<typename T, typename Traits>
169-
bool equals(const std::basic_string_view<T, Traits>& lhs, const std::basic_string_view<T, Traits>& rhs) noexcept
172+
constexpr bool equals(const std::basic_string_view<T, Traits>& lhs, const std::basic_string_view<T, Traits>& rhs) noexcept
173+
{
174+
return lhs.size() == rhs.size() && __builtin_memcmp(lhs.data(), rhs.data(), rhs.size() * sizeof(T)) == 0;
175+
}
176+
177+
constexpr bool equals(const std::string_view& lhs, const std::string_view& rhs) noexcept
178+
{
179+
return equals<>(lhs, rhs);
180+
}
181+
182+
constexpr bool equals(const std::wstring_view& lhs, const std::wstring_view& rhs) noexcept
170183
{
171-
return lhs.size() == rhs.size() && __builtin_memcmp(lhs.data(), rhs.data(), lhs.size() * sizeof(T)) == 0;
184+
return equals<>(lhs, rhs);
172185
}
173186

174187
// Just like _memicmp, but without annoying locales.

0 commit comments

Comments
 (0)