Bug 927407 - Optimizing NS_{Input, Output}StreamIsBuffered to avoid unnecessary main thread I/O in trivial cases
authorDavid Rajchenbach-Teller <dteller@mozilla.com>
Wed, 16 Oct 2013 07:42:00 +0100
changeset 165759 af63dffeb63f8f196668e5b81fa4ebc6bd843302
parent 165758 ec99b2269e95ada1153d72fc4ce7ef75e37fccfc
child 165760 aa7cc951e8210f621d13dd54525ed5c01e65bfa0
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs927407
milestone27.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 927407 - Optimizing NS_{Input, Output}StreamIsBuffered to avoid unnecessary main thread I/O in trivial cases
xpcom/io/nsStreamUtils.cpp
xpcom/io/nsStreamUtils.h
--- a/xpcom/io/nsStreamUtils.cpp
+++ b/xpcom/io/nsStreamUtils.cpp
@@ -10,16 +10,17 @@
 #include "nsCOMPtr.h"
 #include "nsIPipe.h"
 #include "nsIEventTarget.h"
 #include "nsIRunnable.h"
 #include "nsISafeOutputStream.h"
 #include "nsString.h"
 #include "nsIAsyncInputStream.h"
 #include "nsIAsyncOutputStream.h"
+#include "nsIBufferedStreams.h"
 
 using namespace mozilla;
 
 //-----------------------------------------------------------------------------
 
 class nsInputStreamReadyEvent MOZ_FINAL : public nsIRunnable
                                         , public nsIInputStreamCallback
 {
@@ -663,16 +664,21 @@ TestInputStream(nsIInputStream *inStr,
     bool *result = static_cast<bool *>(closure);
     *result = true;
     return NS_ERROR_ABORT;  // don't call me anymore
 }
 
 bool
 NS_InputStreamIsBuffered(nsIInputStream *stream)
 {
+    nsCOMPtr<nsIBufferedInputStream> bufferedIn = do_QueryInterface(stream);
+    if (bufferedIn) {
+        return true;
+    }
+
     bool result = false;
     uint32_t n;
     nsresult rv = stream->ReadSegments(TestInputStream,
                                        &result, 1, &n);
     return result || NS_SUCCEEDED(rv);
 }
 
 static NS_METHOD
@@ -686,16 +692,21 @@ TestOutputStream(nsIOutputStream *outStr
     bool *result = static_cast<bool *>(closure);
     *result = true;
     return NS_ERROR_ABORT;  // don't call me anymore
 }
 
 bool
 NS_OutputStreamIsBuffered(nsIOutputStream *stream)
 {
+    nsCOMPtr<nsIBufferedOutputStream> bufferedOut = do_QueryInterface(stream);
+    if (bufferedOut) {
+        return true;
+    }
+
     bool result = false;
     uint32_t n;
     stream->WriteSegments(TestOutputStream, &result, 1, &n);
     return result;
 }
 
 //-----------------------------------------------------------------------------
 
--- a/xpcom/io/nsStreamUtils.h
+++ b/xpcom/io/nsStreamUtils.h
@@ -126,41 +126,52 @@ NS_CancelAsyncCopy(nsISupports *aCopierC
  *        Note: The data copied to the string may contain null bytes and may
  *        contain non-ASCII values.
  */
 extern nsresult
 NS_ConsumeStream(nsIInputStream *aSource, uint32_t aMaxCount,
                  nsACString &aBuffer);
 
 /**
- * This function tests whether or not the input stream is buffered.  A buffered
+ * This function tests whether or not the input stream is buffered. A buffered
  * input stream is one that implements readSegments.  The test for this is to
- * simply call readSegments, without actually consuming any data from the
+ * 1/ check whether the input stream implements nsIBufferedInputStream;
+ * 2/ if not, call readSegments, without actually consuming any data from the
  * stream, to verify that it functions.
  *
  * NOTE: If the stream is non-blocking and has no data available yet, then this
- * test will fail.  In that case, we return false even though the test is not 
+ * test will fail.  In that case, we return false even though the test is not
  * really conclusive.
  *
+ * PERFORMANCE NOTE: If the stream does not implement nsIBufferedInputStream,
+ * calling readSegments may cause I/O. Therefore, you should avoid calling
+ * this function from the main thread.
+ *
  * @param aInputStream
  *        The input stream to test.
  */
 extern bool
 NS_InputStreamIsBuffered(nsIInputStream *aInputStream);
 
 /**
  * This function tests whether or not the output stream is buffered.  A
  * buffered output stream is one that implements writeSegments.  The test for
- * this is to simply call writeSegments, without actually writing any data into
+ * this is to:
+ * 1/ check whether the output stream implements nsIBufferedOutputStream;
+ * 2/ if not, call writeSegments, without actually writing any data into
  * the stream, to verify that it functions.
  *
  * NOTE: If the stream is non-blocking and has no available space yet, then
  * this test will fail.  In that case, we return false even though the test is
  * not really conclusive.
  *
+ * PERFORMANCE NOTE: If the stream does not implement nsIBufferedOutputStream,
+ * calling writeSegments may cause I/O. Therefore, you should avoid calling
+ * this function from the main thread.
+ *
  * @param aOutputStream
  *        The output stream to test.
  */
 extern bool
 NS_OutputStreamIsBuffered(nsIOutputStream *aOutputStream);
 
 /**
  * This function is intended to be passed to nsIInputStream::ReadSegments to