Bug 1211090 - Add fallocate support to nsIOutputFileStream and use it. r=froydnj
authorGian-Carlo Pascutto <gcp@mozilla.com>
Mon, 21 Dec 2015 17:50:53 +0100
changeset 277148 e3f5398fee0a1108328b2f6a14a7bac486155ffa
parent 277147 2107959cc7598f12a7a1b0471138388732fd1ce8
child 277149 1df4fea9c5025aa91355c9fee1f13e17412cd3bc
push id69391
push usergpascutto@mozilla.com
push dateMon, 21 Dec 2015 16:51:17 +0000
treeherdermozilla-inbound@1df4fea9c502 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1211090
milestone46.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 1211090 - Add fallocate support to nsIOutputFileStream and use it. r=froydnj
netwerk/base/nsFileStreams.cpp
netwerk/base/nsIFileStreams.idl
toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp
--- a/netwerk/base/nsFileStreams.cpp
+++ b/netwerk/base/nsFileStreams.cpp
@@ -16,16 +16,18 @@
 
 #include "private/pprio.h"
 
 #include "nsFileStreams.h"
 #include "nsIFile.h"
 #include "nsReadLine.h"
 #include "nsIClassInfoImpl.h"
 #include "mozilla/ipc/InputStreamUtils.h"
+#include "mozilla/unused.h"
+#include "mozilla/FileUtils.h"
 #include "nsNetCID.h"
 #include "nsXULAppAPI.h"
 
 #define NS_NO_INPUT_BUFFERING 1 // see http://bugzilla.mozilla.org/show_bug.cgi?id=41067
 
 typedef mozilla::ipc::FileDescriptor::PlatformHandleType FileHandleType;
 
 using namespace mozilla::ipc;
@@ -861,16 +863,30 @@ nsFileOutputStream::Init(nsIFile* file, 
         ioFlags = PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE;
     if (perm <= 0)
         perm = 0664;
 
     return MaybeOpen(file, ioFlags, perm,
                      mBehaviorFlags & nsIFileOutputStream::DEFER_OPEN);
 }
 
+NS_IMETHODIMP
+nsFileOutputStream::Preallocate(int64_t aLength)
+{
+    if (!mFD) {
+        return NS_ERROR_NOT_INITIALIZED;
+    }
+
+    if (!mozilla::fallocate(mFD, aLength)) {
+        return NS_ERROR_FAILURE;
+    }
+
+    return NS_OK;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsAtomicFileOutputStream
 
 NS_IMPL_ISUPPORTS_INHERITED(nsAtomicFileOutputStream,
                             nsFileOutputStream,
                             nsISafeOutputStream,
                             nsIOutputStream,
                             nsIFileOutputStream)
--- a/netwerk/base/nsIFileStreams.idl
+++ b/netwerk/base/nsIFileStreams.idl
@@ -82,17 +82,17 @@ interface nsIFileInputStream : nsIInputS
      * allows the OS to delete the file from disk just like POSIX.
      */
     const long SHARE_DELETE = 1<<5;
 };
 
 /**
  * An output stream that lets you stream to a file.
  */
-[scriptable, uuid(e6f68040-c7ec-11d3-8cda-0060b0fc14a3)]
+[scriptable, uuid(e734cac9-1295-4e6f-9684-3ac4e1f91063)]
 interface nsIFileOutputStream : nsIOutputStream
 {
     /**
      * @param file          file to write to
      * @param ioFlags       file open flags listed in prio.h (see
      *                      PR_Open documentation) or -1 to open the
      *                      file in default mode (PR_WRONLY |
      *                      PR_CREATE_FILE | PR_TRUNCATE)
@@ -100,16 +100,25 @@ interface nsIFileOutputStream : nsIOutpu
      *                      use the default permissions (0664)
      * @param behaviorFlags flags specifying various behaviors of the class
      *        (currently none supported)
      */
     void init(in nsIFile file, in long ioFlags, in long perm,
               in long behaviorFlags);
 
     /**
+     * @param length        asks the operating system to allocate storage for
+     *                      this file of at least |length| bytes long, and
+     *                      set the file length to the corresponding size.
+     * @throws NS_ERROR_FAILURE if the preallocation fails.
+     * @throws NS_ERROR_NOT_INITIALIZED if the file is not opened.
+     */
+    [noscript] void preallocate(in long long length);
+
+    /**
      * See the same constant in nsIFileInputStream. The deferred open will
      * be performed when one of the following is called:
      *   - Seek
      *   - Tell
      *   - SetEOF
      *   - Write
      *   - Flush
      *
--- a/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp
@@ -13,20 +13,22 @@
 #include "nsString.h"
 #include "nsIFile.h"
 #include "nsToolkitCompsCID.h"
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
 #include "nsNetUtil.h"
 #include "nsISeekableStream.h"
 #include "nsIBufferedStreams.h"
+#include "nsIFileStreams.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/FileUtils.h"
 #include "mozilla/Logging.h"
+#include "mozilla/unused.h"
 
 using namespace mozilla;
 
 // NSPR_LOG_MODULES=UrlClassifierPrefixSet:5
 static const PRLogModuleInfo *gUrlClassifierPrefixSetLog = nullptr;
 #define LOG(args) MOZ_LOG(gUrlClassifierPrefixSetLog, mozilla::LogLevel::Debug, args)
 #define LOG_ENABLED() MOZ_LOG_TEST(gUrlClassifierPrefixSetLog, mozilla::LogLevel::Debug)
 
@@ -369,22 +371,35 @@ nsUrlClassifierPrefixSet::LoadFromFile(n
   mMemoryInUse = SizeOfIncludingThis(UrlClassifierMallocSizeOf);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsUrlClassifierPrefixSet::StoreToFile(nsIFile* aFile)
 {
-  // Now re-open
   nsCOMPtr<nsIOutputStream> localOutFile;
   nsresult rv = NS_NewLocalFileOutputStream(getter_AddRefs(localOutFile), aFile,
                                             PR_WRONLY | PR_TRUNCATE | PR_CREATE_FILE);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  // Preallocate the file storage
+  {
+    nsCOMPtr<nsIFileOutputStream> fos(do_QueryInterface(localOutFile));
+    Telemetry::AutoTimer<Telemetry::URLCLASSIFIER_PS_FALLOCATE_TIME> timer;
+    int64_t size = 4 * sizeof(uint32_t);
+    uint32_t deltas = mTotalPrefixes - mIndexPrefixes.Length();
+    size += 2 * mIndexPrefixes.Length() * sizeof(uint32_t);
+    size += deltas * sizeof(uint16_t);
+
+    // Ignore failure, the preallocation is a hint and we write out the entire
+    // file later on
+    Unused << fos->Preallocate(size);
+  }
+
   // Convert to buffered stream
   nsCOMPtr<nsIOutputStream> out;
   rv = NS_NewBufferedOutputStream(getter_AddRefs(out), localOutFile,
                                   BUFFER_SIZE);
   NS_ENSURE_SUCCESS(rv, rv);
 
   uint32_t written;
   uint32_t writelen = sizeof(uint32_t);