exponential capacity growth for io::TypedIOBuf
authorPhilip Pronin <philipp@fb.com>
Thu, 17 Oct 2013 03:13:33 +0000 (20:13 -0700)
committerSara Golemon <sgolemon@fb.com>
Thu, 24 Oct 2013 21:53:41 +0000 (14:53 -0700)
Summary:
Amortized cost of `TypedIOBuf::push()` is `O(N)` at this moment.
Unless we're using jemalloc where we can rely on `realloc()`.  In this
diff we switch to exponential growth otherwise.

Test Plan:
built unicorn/test with ASan (and thus without jemalloc), ran
end-to-end tests and verified we no longer spend minutes to build di4

@override-unit-failures

Reviewed By: tudorb@fb.com

FB internal diff: D1015233

folly/io/TypedIOBuf.h

index 3e8d2297cb8e9551e298be6680f90f3e0d716887..90e17126cdd9ea957af0f9d76989eead24d5759e 100644 (file)
@@ -20,6 +20,8 @@
 #include <algorithm>
 #include <iterator>
 #include <type_traits>
+
+#include "folly/Malloc.h"
 #include "folly/io/IOBuf.h"
 
 namespace folly {
@@ -164,8 +166,14 @@ class TypedIOBuf {
    */
   template <class IT>
   void push(IT begin, IT end) {
-    auto n = std::distance(begin, end);
-    reserve(headroom(), n);
+    uint32_t n = std::distance(begin, end);
+    if (usingJEMalloc()) {
+      // Rely on rallocm() and avoid exponential growth to limit
+      // amount of memory wasted.
+      reserve(headroom(), n);
+    } else if (tailroom() < n) {
+      reserve(headroom(), std::max(n, 3 + size() / 2));
+    }
     std::copy(begin, end, writableTail());
     append(n);
   }