[libcxx-commits] [PATCH] D72164: Optimize / partially inline basic_string assignment operator

Martijn Vels via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jan 3 09:09:15 PST 2020


mvels created this revision.
mvels added a project: libc++.
Herald added a reviewer: mclow.lists.
mvels edited the summary of this revision.
mvels added a reviewer: EricWF.
mvels added a parent revision: D72160: Optimize / partially inline basic_string copy constructor.
mvels abandoned this revision.

This change adds an optimization where assigning a short string value to a short string instance is optimized into a direct memory copy.

'As is', this optimization provides a 2X to 3X+ speed up.

BM_StringAssignStr_Empty_Opaque                     5.23ns ± 0%             2.27ns ± 0%  -56.62%          (p=0.008 n=5+5)
BM_StringAssignStr_Empty_Transparent                5.14ns ± 0%             2.27ns ± 0%  -55.89%          (p=0.008 n=5+5)
BM_StringAssignStr_Small_Opaque                     7.69ns ± 0%             2.27ns ± 0%  -70.56%          (p=0.008 n=5+5)
BM_StringAssignStr_Small_Transparent                7.65ns ± 0%             2.26ns ± 0%  -70.41%          (p=0.008 n=5+5)
BM_StringAssignStr_Large_Opaque                     24.4ns ± 0%             25.6ns ± 0%   +5.11%          (p=0.008 n=5+5)
BM_StringAssignStr_Large_Transparent                22.2ns ± 0%             22.9ns ± 0%   +3.43%          (p=0.008 n=5+5)
BM_StringAssignStr_Huge_Opaque                       320ns ± 3%              320ns ± 4%     ~             (p=0.841 n=5+5)
BM_StringAssignStr_Huge_Transparent                  321ns ± 4%              321ns ± 4%     ~             (p=1.000 n=5+5)

Subsequently changing the assignment operator to be inlined (not externally instantiated) provides a speed up of 3X to 5X.

BM_StringAssignStr_Empty_Opaque                     5.25ns ± 1%             1.71ns ± 0%  -67.33%          (p=0.008 n=5+5)
BM_StringAssignStr_Empty_Transparent                5.13ns ± 0%             1.29ns ± 0%  -74.89%          (p=0.008 n=5+5)
BM_StringAssignStr_Small_Opaque                     7.69ns ± 0%             1.71ns ± 0%  -77.70%          (p=0.008 n=5+5)
BM_StringAssignStr_Small_Transparent                7.64ns ± 0%             1.29ns ± 0%  -83.10%          (p=0.008 n=5+5)
BM_StringAssignStr_Large_Opaque                     24.4ns ± 0%             25.3ns ± 0%   +3.97%          (p=0.008 n=5+5)
BM_StringAssignStr_Large_Transparent                22.2ns ± 0%             22.6ns ± 0%   +2.13%          (p=0.008 n=5+5)
BM_StringAssignStr_Huge_Opaque                       325ns ± 5%              315ns ± 6%     ~             (p=0.222 n=5+5)
BM_StringAssignStr_Huge_Transparent                  325ns ± 5%              316ns ± 5%     ~             (p=0.310 n=5+5)


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D72164

Files:
  libcxx/include/string


Index: libcxx/include/string
===================================================================
--- libcxx/include/string
+++ libcxx/include/string
@@ -796,6 +796,10 @@
         _NOEXCEPT;
 #endif
 
+    // Optimization opportunity: do not externally instantiate the copy
+    // constructor, which inlines short string initialization. Long string
+    // initialization is delegated to the (external) __init_long()method,
+    // which results in a 3X-4X speed up for SSO initialization.
     basic_string(const basic_string& __str);
     basic_string(const basic_string& __str, const allocator_type& __a);
 
@@ -874,6 +878,7 @@
     _LIBCPP_INLINE_VISIBILITY
     operator __self_view() const _NOEXCEPT { return __self_view(data(), size()); }
 
+    // Optimization opportunity: do not externally instantiate
     basic_string& operator=(const basic_string& __str);
 
     template <class _Tp, class = typename enable_if<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, void>::type>
@@ -1543,6 +1548,8 @@
     inline
     void __init(size_type __n, value_type __c);
 
+    void __init_long(const basic_string& __str);
+
     template <class _InputIterator>
     inline
     typename enable_if
@@ -1794,6 +1801,20 @@
     traits_type::assign(__p[__sz], value_type());
 }
 
+template <class _CharT, class _Traits, class _Allocator>
+void basic_string<_CharT, _Traits, _Allocator>::__init_long(
+    const basic_string& __str) {
+  const value_type* __s = _VSTD::__to_address(__str.__get_long_pointer());
+  size_type __sz = __str.__get_long_size();
+  size_type __cap = __recommend(__sz);
+  pointer __p = __alloc_traits::allocate(__alloc(), __cap + 1);
+  __set_long_pointer(__p);
+  __set_long_cap(__cap + 1);
+  __set_long_size(__sz);
+  traits_type::copy(_VSTD::__to_address(__p), __s, __sz);
+  traits_type::assign(__p[__sz], value_type());
+}
+
 template <class _CharT, class _Traits, class _Allocator>
 template <class>
 basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, const _Allocator& __a)
@@ -1837,7 +1858,7 @@
     if (!__str.__is_long())
         __r_.first().__r = __str.__r_.first().__r;
     else
-        __init(_VSTD::__to_address(__str.__get_long_pointer()), __str.__get_long_size());
+        __init_long(__str);
 #if _LIBCPP_DEBUG_LEVEL >= 2
     __get_db()->__insert_c(this);
 #endif
@@ -1851,7 +1872,7 @@
     if (!__str.__is_long())
         __r_.first().__r = __str.__r_.first().__r;
     else
-        __init(_VSTD::__to_address(__str.__get_long_pointer()), __str.__get_long_size());
+        __init_long(__str);
 #if _LIBCPP_DEBUG_LEVEL >= 2
     __get_db()->__insert_c(this);
 #endif
@@ -2266,7 +2287,10 @@
     if (this != &__str)
     {
         __copy_assign_alloc(__str);
-        return assign(__str.data(), __str.size());
+        if (__is_long() | __str.__is_long()) {  // LINT: explicit binary or.
+          return assign(__str.data(), __str.size());
+        }
+        __r_.first().__r = __str.__r_.first().__r;
     }
     return *this;
 }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D72164.236074.patch
Type: text/x-patch
Size: 3022 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20200103/36154598/attachment-0001.bin>


More information about the libcxx-commits mailing list