Bug 999383 - optimize Open and Read inter-thread calls in CacheFileIOManager, r=michal
authorHonza Bambas <honzab.moz@firemni.cz>
Sat, 26 Apr 2014 18:42:07 +0200
changeset 198921 9f685a4d608f314fa0532a9f03837c35a7ed3c5d
parent 198920 e03b484bafc3f19a2ac73b3c0785064425fa6bd7
child 198922 0d7bf90091bb3ae78317eb34b0a46c2a32b99dcc
push id3624
push userasasaki@mozilla.com
push dateMon, 09 Jun 2014 21:49:01 +0000
treeherdermozilla-beta@b1a5da15899a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmichal
bugs999383
milestone31.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 999383 - optimize Open and Read inter-thread calls in CacheFileIOManager, r=michal
netwerk/cache2/CacheFile.cpp
netwerk/cache2/CacheFileChunk.cpp
netwerk/cache2/CacheFileIOManager.cpp
netwerk/cache2/CacheFileIOManager.h
netwerk/cache2/CacheFileMetadata.cpp
netwerk/cache2/CacheIndex.cpp
--- a/netwerk/cache2/CacheFile.cpp
+++ b/netwerk/cache2/CacheFile.cpp
@@ -264,17 +264,17 @@ CacheFile::Init(const nsACString &aKey,
       }
     }
 
     if (aPriority)
       flags |= CacheFileIOManager::PRIORITY;
 
     mOpeningFile = true;
     mListener = aCallback;
-    rv = CacheFileIOManager::OpenFile(mKey, flags, this);
+    rv = CacheFileIOManager::OpenFile(mKey, flags, true, this);
     if (NS_FAILED(rv)) {
       mListener = nullptr;
       mOpeningFile = false;
 
       if (aCreateNew) {
         NS_WARNING("Forcing memory-only entry since OpenFile failed");
         LOG(("CacheFile::Init() - CacheFileIOManager::OpenFile() failed "
              "synchronously. We can continue in memory-only mode since "
--- a/netwerk/cache2/CacheFileChunk.cpp
+++ b/netwerk/cache2/CacheFileChunk.cpp
@@ -198,17 +198,17 @@ CacheFileChunk::Read(CacheFileHandle *aH
   nsresult rv;
 
   mRWBuf = static_cast<char *>(moz_xmalloc(aLen));
   mRWBufSize = aLen;
 
   DoMemoryReport(MemorySize());
 
   rv = CacheFileIOManager::Read(aHandle, mIndex * kChunkSize, mRWBuf, aLen,
-                                this);
+                                true, this);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     rv = mIndex ? NS_ERROR_FILE_CORRUPTED : NS_ERROR_FILE_NOT_FOUND;
     SetError(rv);
   } else {
     mState = READING;
     mListener = aCallback;
     mDataSize = aLen;
     mReadHash = aHash;
--- a/netwerk/cache2/CacheFileIOManager.cpp
+++ b/netwerk/cache2/CacheFileIOManager.cpp
@@ -554,41 +554,45 @@ public:
 protected:
   mozilla::Mutex   *mLock;
   mozilla::CondVar *mCondVar;
 };
 
 class OpenFileEvent : public nsRunnable {
 public:
   OpenFileEvent(const nsACString &aKey,
-                uint32_t aFlags,
+                uint32_t aFlags, bool aResultOnAnyThread,
                 CacheFileIOListener *aCallback)
     : mFlags(aFlags)
+    , mResultOnAnyThread(aResultOnAnyThread)
     , mCallback(aCallback)
     , mRV(NS_ERROR_FAILURE)
     , mKey(aKey)
   {
     MOZ_COUNT_CTOR(OpenFileEvent);
 
-    mTarget = static_cast<nsIEventTarget*>(NS_GetCurrentThread());
+    if (!aResultOnAnyThread) {
+      mTarget = static_cast<nsIEventTarget*>(NS_GetCurrentThread());
+      MOZ_ASSERT(mTarget);
+    }
+
     mIOMan = CacheFileIOManager::gInstance;
-    MOZ_ASSERT(mTarget);
 
     MOZ_EVENT_TRACER_NAME_OBJECT(static_cast<nsIRunnable*>(this), aKey.BeginReading());
     MOZ_EVENT_TRACER_WAIT(static_cast<nsIRunnable*>(this), "net::cache::open-background");
   }
 
   ~OpenFileEvent()
   {
     MOZ_COUNT_DTOR(OpenFileEvent);
   }
 
   NS_IMETHOD Run()
   {
-    if (mTarget) {
+    if (mResultOnAnyThread || mTarget) {
       mRV = NS_OK;
 
       if (!(mFlags & CacheFileIOManager::SPECIAL_FILE)) {
         SHA1Sum sum;
         sum.update(mKey.BeginReading(), mKey.Length());
         sum.finish(mHash);
       }
 
@@ -612,92 +616,108 @@ public:
               mHandle->Key() = mKey;
             }
           }
         }
       }
       MOZ_EVENT_TRACER_DONE(static_cast<nsIRunnable*>(this), "net::cache::open-background");
 
       MOZ_EVENT_TRACER_WAIT(static_cast<nsIRunnable*>(this), "net::cache::open-result");
-      nsCOMPtr<nsIEventTarget> target;
-      mTarget.swap(target);
-      target->Dispatch(this, nsIEventTarget::DISPATCH_NORMAL);
-    } else {
+
+      if (mTarget) {
+        nsCOMPtr<nsIEventTarget> target;
+        mTarget.swap(target);
+        return target->Dispatch(this, nsIEventTarget::DISPATCH_NORMAL);
+      }
+    }
+
+    if (!mTarget) {
       MOZ_EVENT_TRACER_EXEC(static_cast<nsIRunnable*>(this), "net::cache::open-result");
       mCallback->OnFileOpened(mHandle, mRV);
       MOZ_EVENT_TRACER_DONE(static_cast<nsIRunnable*>(this), "net::cache::open-result");
     }
+
     return NS_OK;
   }
 
 protected:
   SHA1Sum::Hash                 mHash;
   uint32_t                      mFlags;
+  bool                          mResultOnAnyThread;
   nsCOMPtr<CacheFileIOListener> mCallback;
   nsCOMPtr<nsIEventTarget>      mTarget;
   nsRefPtr<CacheFileIOManager>  mIOMan;
   nsRefPtr<CacheFileHandle>     mHandle;
   nsresult                      mRV;
   nsCString                     mKey;
 };
 
 class ReadEvent : public nsRunnable {
 public:
   ReadEvent(CacheFileHandle *aHandle, int64_t aOffset, char *aBuf,
-            int32_t aCount, CacheFileIOListener *aCallback)
+            int32_t aCount, bool aResultOnAnyThread, CacheFileIOListener *aCallback)
     : mHandle(aHandle)
     , mOffset(aOffset)
     , mBuf(aBuf)
     , mCount(aCount)
+    , mResultOnAnyThread(aResultOnAnyThread)
     , mCallback(aCallback)
     , mRV(NS_ERROR_FAILURE)
   {
     MOZ_COUNT_CTOR(ReadEvent);
-    mTarget = static_cast<nsIEventTarget*>(NS_GetCurrentThread());
+
+    if (!aResultOnAnyThread) {
+      mTarget = static_cast<nsIEventTarget*>(NS_GetCurrentThread());
+    }
 
     MOZ_EVENT_TRACER_NAME_OBJECT(static_cast<nsIRunnable*>(this), aHandle->Key().get());
     MOZ_EVENT_TRACER_WAIT(static_cast<nsIRunnable*>(this), "net::cache::read-background");
   }
 
   ~ReadEvent()
   {
     MOZ_COUNT_DTOR(ReadEvent);
   }
 
   NS_IMETHOD Run()
   {
-    if (mTarget) {
+    if (mResultOnAnyThread || mTarget) {
       MOZ_EVENT_TRACER_EXEC(static_cast<nsIRunnable*>(this), "net::cache::read-background");
       if (mHandle->IsClosed()) {
         mRV = NS_ERROR_NOT_INITIALIZED;
       } else {
         mRV = CacheFileIOManager::gInstance->ReadInternal(
           mHandle, mOffset, mBuf, mCount);
       }
       MOZ_EVENT_TRACER_DONE(static_cast<nsIRunnable*>(this), "net::cache::read-background");
 
       MOZ_EVENT_TRACER_WAIT(static_cast<nsIRunnable*>(this), "net::cache::read-result");
-      nsCOMPtr<nsIEventTarget> target;
-      mTarget.swap(target);
-      target->Dispatch(this, nsIEventTarget::DISPATCH_NORMAL);
-    } else {
+
+      if (mTarget) {
+        nsCOMPtr<nsIEventTarget> target;
+        mTarget.swap(target);
+        return target->Dispatch(this, nsIEventTarget::DISPATCH_NORMAL);
+      }
+    }
+
+    if (!mTarget && mCallback) {
       MOZ_EVENT_TRACER_EXEC(static_cast<nsIRunnable*>(this), "net::cache::read-result");
-      if (mCallback) {
-        mCallback->OnDataRead(mHandle, mBuf, mRV);
-      }
+      mCallback->OnDataRead(mHandle, mBuf, mRV);
       MOZ_EVENT_TRACER_DONE(static_cast<nsIRunnable*>(this), "net::cache::read-result");
     }
+
     return NS_OK;
   }
 
 protected:
   nsRefPtr<CacheFileHandle>     mHandle;
   int64_t                       mOffset;
   char                         *mBuf;
   int32_t                       mCount;
+  bool                          mResultOnAnyThread;
   nsCOMPtr<CacheFileIOListener> mCallback;
   nsCOMPtr<nsIEventTarget>      mTarget;
   nsresult                      mRV;
 };
 
 class WriteEvent : public nsRunnable {
 public:
   WriteEvent(CacheFileHandle *aHandle, int64_t aOffset, const char *aBuf,
@@ -1527,31 +1547,31 @@ CacheFileIOManager::Notify(nsITimer * aT
   }
 
   return NS_OK;
 }
 
 // static
 nsresult
 CacheFileIOManager::OpenFile(const nsACString &aKey,
-                             uint32_t aFlags,
+                             uint32_t aFlags, bool aResultOnAnyThread,
                              CacheFileIOListener *aCallback)
 {
   LOG(("CacheFileIOManager::OpenFile() [key=%s, flags=%d, listener=%p]",
        PromiseFlatCString(aKey).get(), aFlags, aCallback));
 
   nsresult rv;
   nsRefPtr<CacheFileIOManager> ioMan = gInstance;
 
   if (!ioMan) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   bool priority = aFlags & CacheFileIOManager::PRIORITY;
-  nsRefPtr<OpenFileEvent> ev = new OpenFileEvent(aKey, aFlags, aCallback);
+  nsRefPtr<OpenFileEvent> ev = new OpenFileEvent(aKey, aFlags, aResultOnAnyThread, aCallback);
   rv = ioMan->mIOThread->Dispatch(ev, priority
     ? CacheIOThread::OPEN_PRIORITY
     : CacheIOThread::OPEN);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
@@ -1794,31 +1814,31 @@ CacheFileIOManager::CloseHandleInternal(
   }
 
   return NS_OK;
 }
 
 // static
 nsresult
 CacheFileIOManager::Read(CacheFileHandle *aHandle, int64_t aOffset,
-                         char *aBuf, int32_t aCount,
+                         char *aBuf, int32_t aCount, bool aResultOnAnyThread,
                          CacheFileIOListener *aCallback)
 {
   LOG(("CacheFileIOManager::Read() [handle=%p, offset=%lld, count=%d, "
        "listener=%p]", aHandle, aOffset, aCount, aCallback));
 
   nsresult rv;
   nsRefPtr<CacheFileIOManager> ioMan = gInstance;
 
   if (aHandle->IsClosed() || !ioMan) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   nsRefPtr<ReadEvent> ev = new ReadEvent(aHandle, aOffset, aBuf, aCount,
-                                         aCallback);
+                                         aResultOnAnyThread, aCallback);
   rv = ioMan->mIOThread->Dispatch(ev, aHandle->IsPriority()
     ? CacheIOThread::READ_PRIORITY
     : CacheIOThread::READ);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
--- a/netwerk/cache2/CacheFileIOManager.h
+++ b/netwerk/cache2/CacheFileIOManager.h
@@ -233,20 +233,20 @@ public:
   static nsresult ScheduleMetadataWrite(CacheFile * aFile);
   // Remove aFile from the scheduling registry array.
   // WriteMetadataIfNeeded will not be automatically called.
   static nsresult UnscheduleMetadataWrite(CacheFile * aFile);
   // Shuts the scheduling off and flushes all pending metadata writes.
   static nsresult ShutdownMetadataWriteScheduling();
 
   static nsresult OpenFile(const nsACString &aKey,
-                           uint32_t aFlags,
+                           uint32_t aFlags, bool aResultOnAnyThread,
                            CacheFileIOListener *aCallback);
   static nsresult Read(CacheFileHandle *aHandle, int64_t aOffset,
-                       char *aBuf, int32_t aCount,
+                       char *aBuf, int32_t aCount, bool aResultOnAnyThread,
                        CacheFileIOListener *aCallback);
   static nsresult Write(CacheFileHandle *aHandle, int64_t aOffset,
                         const char *aBuf, int32_t aCount, bool aValidate,
                         CacheFileIOListener *aCallback);
   static nsresult DoomFile(CacheFileHandle *aHandle,
                            CacheFileIOListener *aCallback);
   static nsresult DoomFileByKey(const nsACString &aKey,
                                 CacheFileIOListener *aCallback);
--- a/netwerk/cache2/CacheFileMetadata.cpp
+++ b/netwerk/cache2/CacheFileMetadata.cpp
@@ -194,17 +194,17 @@ CacheFileMetadata::ReadMetadata(CacheFil
   mBuf = static_cast<char *>(moz_xmalloc(mBufSize));
 
   DoMemoryReport(MemoryUsage());
 
   LOG(("CacheFileMetadata::ReadMetadata() - Reading metadata from disk, trying "
        "offset=%lld, filesize=%lld [this=%p]", offset, size, this));
 
   mListener = aListener;
-  rv = CacheFileIOManager::Read(mHandle, offset, mBuf, mBufSize, this);
+  rv = CacheFileIOManager::Read(mHandle, offset, mBuf, mBufSize, true, this);
   if (NS_FAILED(rv)) {
     LOG(("CacheFileMetadata::ReadMetadata() - CacheFileIOManager::Read() failed"
          " synchronously, creating empty metadata. [this=%p, rv=0x%08x]",
          this, rv));
 
     mListener = nullptr;
     InitEmptyMetadata();
     aListener->OnMetadataRead(NS_OK);
@@ -624,17 +624,17 @@ CacheFileMetadata::OnDataRead(CacheFileH
     memmove(mBuf + missing, mBuf, mBufSize);
     mBufSize += missing;
 
     DoMemoryReport(MemoryUsage());
 
     LOG(("CacheFileMetadata::OnDataRead() - We need to read %d more bytes to "
          "have full metadata. [this=%p]", missing, this));
 
-    rv = CacheFileIOManager::Read(mHandle, realOffset, mBuf, missing, this);
+    rv = CacheFileIOManager::Read(mHandle, realOffset, mBuf, missing, true, this);
     if (NS_FAILED(rv)) {
       LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() "
            "failed synchronously, creating empty metadata. [this=%p, "
            "rv=0x%08x]", this, rv));
 
       InitEmptyMetadata();
       retval = NS_OK;
 
--- a/netwerk/cache2/CacheIndex.cpp
+++ b/netwerk/cache2/CacheIndex.cpp
@@ -1464,16 +1464,17 @@ CacheIndex::WriteIndexToDisk()
   ChangeState(WRITING);
 
   mProcessEntries = mIndexStats.ActiveEntriesCount();
 
   mIndexFileOpener = new FileOpenHelper(this);
   rv = CacheFileIOManager::OpenFile(NS_LITERAL_CSTRING(kTempIndexName),
                                     CacheFileIOManager::SPECIAL_FILE |
                                     CacheFileIOManager::CREATE,
+                                    true,
                                     mIndexFileOpener);
   if (NS_FAILED(rv)) {
     LOG(("CacheIndex::WriteIndexToDisk() - Can't open file [rv=0x%08x]", rv));
     FinishWrite(false);
     return;
   }
 
   // Write index header to a buffer, it will be written to disk together with
@@ -1909,39 +1910,42 @@ CacheIndex::ReadIndexFromDisk()
   MOZ_ASSERT(mState == INITIAL);
 
   ChangeState(READING);
 
   mIndexFileOpener = new FileOpenHelper(this);
   rv = CacheFileIOManager::OpenFile(NS_LITERAL_CSTRING(kIndexName),
                                     CacheFileIOManager::SPECIAL_FILE |
                                     CacheFileIOManager::OPEN,
+                                    true,
                                     mIndexFileOpener);
   if (NS_FAILED(rv)) {
     LOG(("CacheIndex::ReadIndexFromDisk() - CacheFileIOManager::OpenFile() "
          "failed [rv=0x%08x, file=%s]", rv, kIndexName));
     FinishRead(false);
     return;
   }
 
   mJournalFileOpener = new FileOpenHelper(this);
   rv = CacheFileIOManager::OpenFile(NS_LITERAL_CSTRING(kJournalName),
                                     CacheFileIOManager::SPECIAL_FILE |
                                     CacheFileIOManager::OPEN,
+                                    true,
                                     mJournalFileOpener);
   if (NS_FAILED(rv)) {
     LOG(("CacheIndex::ReadIndexFromDisk() - CacheFileIOManager::OpenFile() "
          "failed [rv=0x%08x, file=%s]", rv, kJournalName));
     FinishRead(false);
   }
 
   mTmpFileOpener = new FileOpenHelper(this);
   rv = CacheFileIOManager::OpenFile(NS_LITERAL_CSTRING(kTempIndexName),
                                     CacheFileIOManager::SPECIAL_FILE |
                                     CacheFileIOManager::OPEN,
+                                    true,
                                     mTmpFileOpener);
   if (NS_FAILED(rv)) {
     LOG(("CacheIndex::ReadIndexFromDisk() - CacheFileIOManager::OpenFile() "
          "failed [rv=0x%08x, file=%s]", rv, kTempIndexName));
     FinishRead(false);
   }
 }
 
@@ -1972,17 +1976,17 @@ CacheIndex::StartReadingIndex()
 
   AllocBuffer();
   mSkipEntries = 0;
   mRWHash = new CacheHash();
 
   mRWBufPos = std::min(mRWBufSize,
                        static_cast<uint32_t>(mIndexHandle->FileSize()));
 
-  rv = CacheFileIOManager::Read(mIndexHandle, 0, mRWBuf, mRWBufPos, this);
+  rv = CacheFileIOManager::Read(mIndexHandle, 0, mRWBuf, mRWBufPos, true, this);
   if (NS_FAILED(rv)) {
     LOG(("CacheIndex::StartReadingIndex() - CacheFileIOManager::Read() failed "
          "synchronously [rv=0x%08x]", rv));
     FinishRead(false);
   }
 }
 
 void
@@ -2097,17 +2101,17 @@ CacheIndex::ParseRecords()
 
   pos = mRWBufPos;
   uint32_t toRead = std::min(mRWBufSize - pos,
                              static_cast<uint32_t>(mIndexHandle->FileSize() -
                                                    fileOffset));
   mRWBufPos = pos + toRead;
 
   rv = CacheFileIOManager::Read(mIndexHandle, fileOffset, mRWBuf + pos, toRead,
-                                this);
+                                true, this);
   if (NS_FAILED(rv)) {
     LOG(("CacheIndex::ParseRecords() - CacheFileIOManager::Read() failed "
          "synchronously [rv=0x%08x]", rv));
     FinishRead(false);
     return;
   }
 }
 
@@ -2135,17 +2139,17 @@ CacheIndex::StartReadingJournal()
   }
 
   mSkipEntries = 0;
   mRWHash = new CacheHash();
 
   mRWBufPos = std::min(mRWBufSize,
                        static_cast<uint32_t>(mJournalHandle->FileSize()));
 
-  rv = CacheFileIOManager::Read(mJournalHandle, 0, mRWBuf, mRWBufPos, this);
+  rv = CacheFileIOManager::Read(mJournalHandle, 0, mRWBuf, mRWBufPos, true, this);
   if (NS_FAILED(rv)) {
     LOG(("CacheIndex::StartReadingJournal() - CacheFileIOManager::Read() failed"
          " synchronously [rv=0x%08x]", rv));
     FinishRead(false);
   }
 }
 
 void
@@ -2210,17 +2214,17 @@ CacheIndex::ParseJournal()
 
   pos = mRWBufPos;
   uint32_t toRead = std::min(mRWBufSize - pos,
                              static_cast<uint32_t>(mJournalHandle->FileSize() -
                                                    fileOffset));
   mRWBufPos = pos + toRead;
 
   rv = CacheFileIOManager::Read(mJournalHandle, fileOffset, mRWBuf + pos,
-                                toRead, this);
+                                toRead, true, this);
   if (NS_FAILED(rv)) {
     LOG(("CacheIndex::ParseJournal() - CacheFileIOManager::Read() failed "
          "synchronously [rv=0x%08x]", rv));
     FinishRead(false);
     return;
   }
 }