[libcxx] r327064 - Low-hanging fruit optimization in string::__move_assign().

Vedant Kumar via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 8 13:15:26 PST 2018


Author: vedantk
Date: Thu Mar  8 13:15:26 2018
New Revision: 327064

URL: http://llvm.org/viewvc/llvm-project?rev=327064&view=rev
Log:
Low-hanging fruit optimization in string::__move_assign().

shrink_to_fit() ends up doing a lot work to get information that we
already know since we just called clear(). This change seems concise
enough to be worth the couple extra lines and my benchmarks show that it
is indeed a pretty decent win. It looks like the same thing is going on
twice in __copy_assign_alloc(), but I didn't want to go overboard since
this is my first contribution to llvm/libc++.

Patch by Timothy VanSlyke!

Differential Revision: https://reviews.llvm.org/D41976

Added:
    libcxx/trunk/test/libcxx/strings/basic.string/string.modifiers/clear_and_shrink_db1.pass.cpp
Modified:
    libcxx/trunk/include/string

Modified: libcxx/trunk/include/string
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/string?rev=327064&r1=327063&r2=327064&view=diff
==============================================================================
--- libcxx/trunk/include/string (original)
+++ libcxx/trunk/include/string Thu Mar  8 13:15:26 2018
@@ -1257,6 +1257,8 @@ public:
 
     _LIBCPP_INLINE_VISIBILITY bool __invariants() const;
 
+    _LIBCPP_INLINE_VISIBILITY void __clear_and_shrink();
+    
     _LIBCPP_INLINE_VISIBILITY
     bool __is_long() const _NOEXCEPT
         {return bool(__r_.first().__s.__size_ & __short_mask);}
@@ -1426,16 +1428,14 @@ private:
             {
                 if (!__str.__is_long())
                 {
-                    clear();
-                    shrink_to_fit();
+                    __clear_and_shrink();
                     __alloc() = __str.__alloc();
                 }
                 else
                 {
                     allocator_type __a = __str.__alloc();
                     pointer __p = __alloc_traits::allocate(__a, __str.__get_long_cap());
-                    clear();
-                    shrink_to_fit();
+                    __clear_and_shrink();
                     __alloc() = _VSTD::move(__a);
                     __set_long_pointer(__p);
                     __set_long_cap(__str.__get_long_cap());
@@ -2125,8 +2125,7 @@ basic_string<_CharT, _Traits, _Allocator
     _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value)
 #endif
 {
-    clear();
-    shrink_to_fit();
+    __clear_and_shrink();
     __r_.first() = __str.__r_.first();
     __move_assign_alloc(__str);
     __str.__zero();
@@ -3579,6 +3578,22 @@ basic_string<_CharT, _Traits, _Allocator
     return true;
 }
 
+// __clear_and_shrink
+
+template<class _CharT, class _Traits, class _Allocator>
+inline _LIBCPP_INLINE_VISIBILITY
+void 
+basic_string<_CharT, _Traits, _Allocator>::__clear_and_shrink()
+{
+    clear();
+    if(__is_long())
+    {
+        __alloc_traits::deallocate(__alloc(), __get_long_pointer(), capacity() + 1);
+        __set_long_cap(0);
+        __set_short_size(0);
+    }
+} 
+
 // operator==
 
 template<class _CharT, class _Traits, class _Allocator>

Added: libcxx/trunk/test/libcxx/strings/basic.string/string.modifiers/clear_and_shrink_db1.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/strings/basic.string/string.modifiers/clear_and_shrink_db1.pass.cpp?rev=327064&view=auto
==============================================================================
--- libcxx/trunk/test/libcxx/strings/basic.string/string.modifiers/clear_and_shrink_db1.pass.cpp (added)
+++ libcxx/trunk/test/libcxx/strings/basic.string/string.modifiers/clear_and_shrink_db1.pass.cpp Thu Mar  8 13:15:26 2018
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <string>
+
+// Call __clear_and_shrink() and ensure string invariants hold
+
+#if _LIBCPP_DEBUG >= 1
+
+#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
+
+#include <string>
+#include <cassert>
+
+int main()
+{
+    std::string l = "Long string so that allocation definitely, for sure, absolutely happens. Probably.";
+    std::string s = "short";
+
+    assert(l.__invariants());
+    assert(s.__invariants());
+    
+    s.__clear_and_shrink();
+    assert(s.__invariants());
+    assert(s.size() == 0);
+
+    { 
+    std::string::size_type cap = l.capacity();
+    l.__clear_and_shrink();
+    assert(l.__invariants());
+    assert(l.size() == 0);
+    assert(l.capacity() < cap);
+    }
+}
+
+#else
+
+int main()
+{
+}
+
+#endif




More information about the cfe-commits mailing list