Bug 1503961 - part 2 - do a single allocation for the linearized buffer; r=nbp
authorNathan Froyd <froydnj@mozilla.com>
Mon, 19 Nov 2018 11:21:09 -0500
changeset 503521 f949c4870f0267c86506199a8bbcedda82129c54
parent 503520 9718b942ff558203eaea91981084e9329fbf52a7
child 503522 73e025041c50a4ccc3078dd97971d119269f3e0e
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1503961
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1503961 - part 2 - do a single allocation for the linearized buffer; r=nbp This change should eliminate the repeated copying we see on some testcases.
js/src/vm/Xdr.cpp
--- a/js/src/vm/Xdr.cpp
+++ b/js/src/vm/Xdr.cpp
@@ -448,27 +448,46 @@ XDRIncrementalEncoder::linearize(JS::Tra
         alignLen = ComputeByteAlignment(buffer.length(), alignLen);
         if (!buffer.appendN(0, alignLen)) {
             ReportOutOfMemory(cx());
             return fail(JS::TranscodeResult_Throw);
         }
     }
 
     // Visit the tree parts in a depth first order to linearize the bits.
+    // Calculate the total length first so we don't incur repeated copying
+    // and zeroing of memory for large trees.
     DepthFirstSliceIterator dfs(cx(), tree_);
 
+    size_t totalLength = buffer.length();
+    auto sliceCounter = [&](const Slice& slice) -> bool {
+        totalLength += slice.sliceLength;
+        return true;
+    };
+
+    if (!dfs.iterate(sliceCounter)) {
+        ReportOutOfMemory(cx());
+        return fail(JS::TranscodeResult_Throw);
+    };
+
+    if (!buffer.reserve(totalLength)) {
+        ReportOutOfMemory(cx());
+        return fail(JS::TranscodeResult_Throw);
+    }
+
     auto sliceCopier = [&](const Slice& slice) -> bool {
         // Copy the bytes associated with the current slice to the transcode
         // buffer which would be serialized.
         MOZ_ASSERT(slice.sliceBegin <= slices_.length());
         MOZ_ASSERT(slice.sliceBegin + slice.sliceLength <= slices_.length());
         MOZ_ASSERT(buffer.length() % sizeof(XDRAlignment) == 0);
         MOZ_ASSERT(slice.sliceLength % sizeof(XDRAlignment) == 0);
 
-        return buffer.append(slices_.begin() + slice.sliceBegin, slice.sliceLength);
+        buffer.infallibleAppend(slices_.begin() + slice.sliceBegin, slice.sliceLength);
+        return true;
     };
 
     if (!dfs.iterate(sliceCopier)) {
         ReportOutOfMemory(cx());
         return fail(JS::TranscodeResult_Throw);
     }
 
     tree_.clearAndCompact();