bug 625383 - optimize http chunked decoder memmoves r=hurley
authorPatrick McManus <mcmanus@ducksong.com>
Fri, 31 Jan 2014 22:00:20 -0500
changeset 166812 73caaea5844f87837d7cb9adcbc152e1b7857fd9
parent 166811 5c04b296c127b188fe3a983322a6e54a1a1bc0bf
child 166813 c8abc650f217bf737ba0c4e0cf60b028d0f420e2
push id26152
push usercbook@mozilla.com
push dateWed, 05 Feb 2014 12:20:14 +0000
treeherdermozilla-central@8f7033c595b9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershurley
bugs625383
milestone30.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 625383 - optimize http chunked decoder memmoves r=hurley
netwerk/protocol/http/nsHttpTransaction.cpp
--- a/netwerk/protocol/http/nsHttpTransaction.cpp
+++ b/netwerk/protocol/http/nsHttpTransaction.cpp
@@ -671,16 +671,38 @@ nsHttpTransaction::WritePipeSegment(nsIO
     if (trans->TimingEnabled() && trans->mTimings.responseStart.IsNull()) {
         trans->mTimings.responseStart = TimeStamp::Now();
     }
 
     nsresult rv;
     //
     // OK, now let the caller fill this segment with data.
     //
+    if (!trans->mHaveAllHeaders) {
+        // Reading too far ahead on a chunked encoding is expensive (see below)
+        // so limit header reads to 1KB to minimize any potential damage while
+        // we figure out the message delimiter.
+        count = std::min(count, 1024U);
+    } else if (trans->mChunkedDecoder) {
+        // The API in use requires us to return entity data in 1 contiguous
+        // buffer supplied by the caller. That means
+        // all entity data needs to be moved up to cover gaps created by
+        // stripping the chunk length. We can mitigate this problem by
+        // doing short reads when we are parsing chunk lengths and limiting
+        // reads in the middle of chunks to the remaining chunk size to
+        // increase the frequency of chunk markers naturally aligning
+        // at the start.
+        if (!trans->mChunkedDecoder->GetChunkRemaining()) {
+            count = std::min(count, 6U); // 6 is 4 hex chars + CRLF
+        } else {
+            // extra 2 bytes is for CRLF that terminates the chunk
+            count = std::min(count,
+                             trans->mChunkedDecoder->GetChunkRemaining() + 2);
+        }
+    }
     rv = trans->mWriter->OnWriteSegment(buf, count, countWritten);
     if (NS_FAILED(rv)) return rv; // caller didn't want to write anything
 
     if (!trans->mReceivedData) {
         MOZ_EVENT_TRACER_MARK(static_cast<nsAHttpTransaction*>(trans),
                               "net::http::first-read");
     }