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 180773 9f685a4d608f314fa0532a9f03837c35a7ed3c5d
parent 180772 e03b484bafc3f19a2ac73b3c0785064425fa6bd7
child 180774 0d7bf90091bb3ae78317eb34b0a46c2a32b99dcc
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersmichal
bugs999383
milestone31.0a1
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;
   }
 }