Bug 1286798 - Part 37: Always preallocate quota when initializing a snapshot; r=asuth
authorJan Varga <jan.varga@gmail.com>
Thu, 29 Nov 2018 21:49:14 +0100
changeset 508035 52e5be69837d8effb5f58181ac0e9166bd440fd7
parent 508034 d5f866efde44d0e6d375dc7bcb24b86f21023103
child 508036 ef64949fc1aa9e951bcbd0facbd8309ef7ccabf9
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth
bugs1286798
milestone65.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 1286798 - Part 37: Always preallocate quota when initializing a snapshot; r=asuth Besides always preallocating quota we now also preallocate more. This mitigates number of additional sync calls.
dom/localstorage/ActorsChild.cpp
dom/localstorage/ActorsChild.h
dom/localstorage/ActorsParent.cpp
dom/localstorage/LSDatabase.cpp
dom/localstorage/LSDatabase.h
dom/localstorage/PBackgroundLSDatabase.ipdl
--- a/dom/localstorage/ActorsChild.cpp
+++ b/dom/localstorage/ActorsChild.cpp
@@ -75,17 +75,19 @@ LSDatabaseChild::RecvRequestAllowToClose
     //       However, we probably shouldn't do that if we are shutting down.
   }
 
   return IPC_OK();
 }
 
 PBackgroundLSSnapshotChild*
 LSDatabaseChild::AllocPBackgroundLSSnapshotChild(const nsString& aDocumentURI,
+                                                 const bool& aIncreasePeakUsage,
                                                  const int64_t& aRequestedSize,
+                                                 const int64_t& aMinSize,
                                                  LSSnapshotInitInfo* aInitInfo)
 {
   MOZ_CRASH("PBackgroundLSSnapshotChild actor should be manually constructed!");
 }
 
 bool
 LSDatabaseChild::DeallocPBackgroundLSSnapshotChild(
                                              PBackgroundLSSnapshotChild* aActor)
--- a/dom/localstorage/ActorsChild.h
+++ b/dom/localstorage/ActorsChild.h
@@ -63,17 +63,19 @@ private:
   void
   ActorDestroy(ActorDestroyReason aWhy) override;
 
   mozilla::ipc::IPCResult
   RecvRequestAllowToClose() override;
 
   PBackgroundLSSnapshotChild*
   AllocPBackgroundLSSnapshotChild(const nsString& aDocumentURI,
+                                  const bool& aIncreasePeakUsage,
                                   const int64_t& aRequestedSize,
+                                  const int64_t& aMinSize,
                                   LSSnapshotInitInfo* aInitInfo) override;
 
   bool
   DeallocPBackgroundLSSnapshotChild(PBackgroundLSSnapshotChild* aActor)
                                     override;
 };
 
 class LSObserverChild final
--- a/dom/localstorage/ActorsParent.cpp
+++ b/dom/localstorage/ActorsParent.cpp
@@ -1385,18 +1385,17 @@ public:
 
   void
   NoteActiveDatabase(Database* aDatabase);
 
   void
   NoteInactiveDatabase(Database* aDatabase);
 
   void
-  GetSnapshotInitInfo(int64_t aRequestedSize,
-                      nsTHashtable<nsStringHashKey>& aLoadedItems,
+  GetSnapshotInitInfo(nsTHashtable<nsStringHashKey>& aLoadedItems,
                       nsTArray<LSItemInfo>& aItemInfos,
                       uint32_t& aTotalLength,
                       int64_t& aInitialUsage,
                       int64_t& aPeakUsage,
                       LSSnapshot::LoadState& aLoadState);
 
   void
   GetItem(const nsString& aKey, nsString& aValue) const;
@@ -1425,25 +1424,29 @@ public:
   PrivateBrowsingClear();
 
   void
   BeginUpdateBatch(int64_t aSnapshotInitialUsage);
 
   void
   EndUpdateBatch(int64_t aSnapshotPeakUsage);
 
-  bool
-  UpdateUsage(int64_t aDelta);
+  int64_t
+  RequestUpdateUsage(int64_t aRequestedSize,
+                     int64_t aMinSize);
 
   NS_INLINE_DECL_REFCOUNTING(Datastore)
 
 private:
   // Reference counted.
   ~Datastore();
 
+  bool
+  UpdateUsage(int64_t aDelta);
+
   void
   MaybeClose();
 
   void
   ConnectionClosedCallback();
 
   void
   CleanupMetadata();
@@ -1646,23 +1649,27 @@ private:
   mozilla::ipc::IPCResult
   RecvDeleteMe() override;
 
   mozilla::ipc::IPCResult
   RecvAllowToClose() override;
 
   PBackgroundLSSnapshotParent*
   AllocPBackgroundLSSnapshotParent(const nsString& aDocumentURI,
+                                   const bool& aIncreasePeakUsage,
                                    const int64_t& aRequestedSize,
+                                   const int64_t& aMinSize,
                                    LSSnapshotInitInfo* aInitInfo) override;
 
   mozilla::ipc::IPCResult
   RecvPBackgroundLSSnapshotConstructor(PBackgroundLSSnapshotParent* aActor,
                                        const nsString& aDocumentURI,
+                                       const bool& aIncreasePeakUsage,
                                        const int64_t& aRequestedSize,
+                                       const int64_t& aMinSize,
                                        LSSnapshotInitInfo* aInitInfo) override;
 
   bool
   DeallocPBackgroundLSSnapshotParent(PBackgroundLSSnapshotParent* aActor)
                                      override;
 };
 
 class Snapshot final
@@ -3752,18 +3759,17 @@ Datastore::NoteInactiveDatabase(Database
       MOZ_ASSERT(ok);
     }
 
     mPendingUsageDeltas.Clear();
   }
 }
 
 void
-Datastore::GetSnapshotInitInfo(int64_t aRequestedSize,
-                               nsTHashtable<nsStringHashKey>& aLoadedItems,
+Datastore::GetSnapshotInitInfo(nsTHashtable<nsStringHashKey>& aLoadedItems,
                                nsTArray<LSItemInfo>& aItemInfos,
                                uint32_t& aTotalLength,
                                int64_t& aInitialUsage,
                                int64_t& aPeakUsage,
                                LSSnapshot::LoadState& aLoadState)
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(!mClosed);
@@ -3827,19 +3833,16 @@ Datastore::GetSnapshotInitInfo(int64_t a
     MOZ_ASSERT(aItemInfos.Length() < mKeys.Length());
     aLoadState = LSSnapshot::LoadState::Partial;
   }
 
   aTotalLength = mValues.Count();
 
   aInitialUsage = mUsage;
   aPeakUsage = aInitialUsage;
-  if (aRequestedSize && UpdateUsage(aRequestedSize)) {
-    aPeakUsage += aRequestedSize;
-  }
 }
 
 void
 Datastore::GetItem(const nsString& aKey, nsString& aValue) const
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(!mClosed);
 
@@ -4073,16 +4076,35 @@ Datastore::EndUpdateBatch(int64_t aSnaps
     mConnection->EndUpdateBatch();
   }
 
 #ifdef DEBUG
   mInUpdateBatch = false;
 #endif
 }
 
+int64_t
+Datastore::RequestUpdateUsage(int64_t aRequestedSize,
+                              int64_t aMinSize)
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(aRequestedSize > 0);
+  MOZ_ASSERT(aMinSize > 0);
+
+  if (UpdateUsage(aRequestedSize)) {
+    return aRequestedSize;
+  }
+
+  if (UpdateUsage(aMinSize)) {
+    return aMinSize;
+  }
+
+  return 0;
+}
+
 bool
 Datastore::UpdateUsage(int64_t aDelta)
 {
   AssertIsOnBackgroundThread();
 
   // Check internal LocalStorage origin limit.
   int64_t newUsage = mUsage + aDelta;
   if (newUsage > gOriginLimitKB * 1024) {
@@ -4406,22 +4428,29 @@ Database::RecvAllowToClose()
 
   AllowToClose();
 
   return IPC_OK();
 }
 
 PBackgroundLSSnapshotParent*
 Database::AllocPBackgroundLSSnapshotParent(const nsString& aDocumentURI,
+                                           const bool& aIncreasePeakUsage,
                                            const int64_t& aRequestedSize,
+                                           const int64_t& aMinSize,
                                            LSSnapshotInitInfo* aInitInfo)
 {
   AssertIsOnBackgroundThread();
 
-  if (NS_WARN_IF(aRequestedSize < 0)) {
+  if (NS_WARN_IF(aIncreasePeakUsage && aRequestedSize <= 0)) {
+    ASSERT_UNLESS_FUZZING();
+    return nullptr;
+  }
+
+  if (NS_WARN_IF(aIncreasePeakUsage && aMinSize <= 0)) {
     ASSERT_UNLESS_FUZZING();
     return nullptr;
   }
 
   if (NS_WARN_IF(mAllowedToClose)) {
     ASSERT_UNLESS_FUZZING();
     return nullptr;
   }
@@ -4431,42 +4460,49 @@ Database::AllocPBackgroundLSSnapshotPare
   // Transfer ownership to IPDL.
   return snapshot.forget().take();
 }
 
 mozilla::ipc::IPCResult
 Database::RecvPBackgroundLSSnapshotConstructor(
                                             PBackgroundLSSnapshotParent* aActor,
                                             const nsString& aDocumentURI,
+                                            const bool& aIncreasePeakUsage,
                                             const int64_t& aRequestedSize,
+                                            const int64_t& aMinSize,
                                             LSSnapshotInitInfo* aInitInfo)
 {
   AssertIsOnBackgroundThread();
-  MOZ_ASSERT(aRequestedSize >= 0);
+  MOZ_ASSERT_IF(aIncreasePeakUsage, aRequestedSize > 0);
+  MOZ_ASSERT_IF(aIncreasePeakUsage, aMinSize > 0);
   MOZ_ASSERT(aInitInfo);
   MOZ_ASSERT(!mAllowedToClose);
 
   auto* snapshot = static_cast<Snapshot*>(aActor);
 
   // TODO: This can be optimized depending on which operation triggers snapshot
   //       creation. For example clear() doesn't need to receive items at all.
   nsTHashtable<nsStringHashKey> loadedItems;
   nsTArray<LSItemInfo> itemInfos;
   uint32_t totalLength;
   int64_t initialUsage;
   int64_t peakUsage;
   LSSnapshot::LoadState loadState;
-  mDatastore->GetSnapshotInitInfo(aRequestedSize,
-                                  loadedItems,
+  mDatastore->GetSnapshotInitInfo(loadedItems,
                                   itemInfos,
                                   totalLength,
                                   initialUsage,
                                   peakUsage,
                                   loadState);
 
+  if (aIncreasePeakUsage) {
+    int64_t size = mDatastore->RequestUpdateUsage(aRequestedSize, aMinSize);
+    peakUsage += size;
+  }
+
   snapshot->Init(loadedItems, totalLength, initialUsage, peakUsage, loadState);
 
   RegisterSnapshot(snapshot);
 
   aInitInfo->itemInfos() = std::move(itemInfos);
   aInitInfo->totalLength() = totalLength;
   aInitInfo->initialUsage() = initialUsage;
   aInitInfo->peakUsage() = peakUsage;
@@ -4776,25 +4812,21 @@ Snapshot::RecvIncreasePeakUsage(const in
     return IPC_FAIL_NO_REASON(this);
   }
 
   if (NS_WARN_IF(mFinishReceived)) {
     ASSERT_UNLESS_FUZZING();
     return IPC_FAIL_NO_REASON(this);
   }
 
-  if (mDatastore->UpdateUsage(aRequestedSize)) {
-    mPeakUsage += aRequestedSize;
-    *aSize = aRequestedSize;
-  } else if (mDatastore->UpdateUsage(aMinSize)) {
-    mPeakUsage += aMinSize;
-    *aSize = aMinSize;
-  } else {
-    *aSize = 0;
-  }
+  int64_t size = mDatastore->RequestUpdateUsage(aRequestedSize, aMinSize);
+
+  mPeakUsage += size;
+
+  *aSize = size;
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 Snapshot::RecvPing()
 {
   AssertIsOnBackgroundThread();
--- a/dom/localstorage/LSDatabase.cpp
+++ b/dom/localstorage/LSDatabase.cpp
@@ -96,17 +96,17 @@ nsresult
 LSDatabase::GetLength(LSObject* aObject,
                       uint32_t* aResult)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aObject);
   MOZ_ASSERT(mActor);
   MOZ_ASSERT(!mAllowedToClose);
 
-  nsresult rv = EnsureSnapshot(aObject, /* aRequestedBySetItem */ false);
+  nsresult rv = EnsureSnapshot(aObject);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   rv = mSnapshot->GetLength(aResult);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
@@ -119,17 +119,17 @@ LSDatabase::GetKey(LSObject* aObject,
                    uint32_t aIndex,
                    nsAString& aResult)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aObject);
   MOZ_ASSERT(mActor);
   MOZ_ASSERT(!mAllowedToClose);
 
-  nsresult rv = EnsureSnapshot(aObject, /* aRequestedBySetItem */ false);
+  nsresult rv = EnsureSnapshot(aObject);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   rv = mSnapshot->GetKey(aIndex, aResult);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
@@ -142,17 +142,17 @@ LSDatabase::GetItem(LSObject* aObject,
                     const nsAString& aKey,
                     nsAString& aResult)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aObject);
   MOZ_ASSERT(mActor);
   MOZ_ASSERT(!mAllowedToClose);
 
-  nsresult rv = EnsureSnapshot(aObject, /* aRequestedBySetItem */ false);
+  nsresult rv = EnsureSnapshot(aObject);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   rv = mSnapshot->GetItem(aKey, aResult);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
@@ -164,17 +164,17 @@ nsresult
 LSDatabase::GetKeys(LSObject* aObject,
                     nsTArray<nsString>& aKeys)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aObject);
   MOZ_ASSERT(mActor);
   MOZ_ASSERT(!mAllowedToClose);
 
-  nsresult rv = EnsureSnapshot(aObject, /* aRequestedBySetItem */ false);
+  nsresult rv = EnsureSnapshot(aObject);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   rv = mSnapshot->GetKeys(aKeys);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
@@ -188,17 +188,17 @@ LSDatabase::SetItem(LSObject* aObject,
                     const nsAString& aValue,
                     LSNotifyInfo& aNotifyInfo)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aObject);
   MOZ_ASSERT(mActor);
   MOZ_ASSERT(!mAllowedToClose);
 
-  nsresult rv = EnsureSnapshot(aObject, /* aRequestedBySetItem */ true);
+  nsresult rv = EnsureSnapshot(aObject);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   rv = mSnapshot->SetItem(aKey, aValue, aNotifyInfo);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
@@ -211,17 +211,17 @@ LSDatabase::RemoveItem(LSObject* aObject
                        const nsAString& aKey,
                        LSNotifyInfo& aNotifyInfo)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aObject);
   MOZ_ASSERT(mActor);
   MOZ_ASSERT(!mAllowedToClose);
 
-  nsresult rv = EnsureSnapshot(aObject, /* aRequestedBySetItem */ false);
+  nsresult rv = EnsureSnapshot(aObject);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   rv = mSnapshot->RemoveItem(aKey, aNotifyInfo);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
@@ -233,17 +233,17 @@ nsresult
 LSDatabase::Clear(LSObject* aObject,
                   LSNotifyInfo& aNotifyInfo)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aObject);
   MOZ_ASSERT(mActor);
   MOZ_ASSERT(!mAllowedToClose);
 
-  nsresult rv = EnsureSnapshot(aObject, /* aRequestedBySetItem */ false);
+  nsresult rv = EnsureSnapshot(aObject);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   rv = mSnapshot->Clear(aNotifyInfo);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
@@ -258,19 +258,17 @@ LSDatabase::BeginExplicitSnapshot(LSObje
   MOZ_ASSERT(aObject);
   MOZ_ASSERT(mActor);
   MOZ_ASSERT(!mAllowedToClose);
 
   if (mSnapshot) {
     return NS_ERROR_ALREADY_INITIALIZED;
   }
 
-  nsresult rv = EnsureSnapshot(aObject,
-                               /* aRequestedBySetItem */ false,
-                               /* aExplicit */ true);
+  nsresult rv = EnsureSnapshot(aObject, /* aExplicit */ true);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   return NS_OK;
 }
 
 nsresult
@@ -292,39 +290,38 @@ LSDatabase::EndExplicitSnapshot(LSObject
     return rv;
   }
 
   return NS_OK;
 }
 
 nsresult
 LSDatabase::EnsureSnapshot(LSObject* aObject,
-                           bool aRequestedBySetItem,
                            bool aExplicit)
 {
   MOZ_ASSERT(aObject);
   MOZ_ASSERT(mActor);
   MOZ_ASSERT_IF(mSnapshot, !aExplicit);
   MOZ_ASSERT(!mAllowedToClose);
 
   if (mSnapshot) {
     return NS_OK;
   }
 
   RefPtr<LSSnapshot> snapshot = new LSSnapshot(this);
 
   LSSnapshotChild* actor = new LSSnapshotChild(snapshot);
 
-  int64_t requestedSize = aRequestedBySetItem ? 4096 : 0;
-
   LSSnapshotInitInfo initInfo;
   bool ok =
     mActor->SendPBackgroundLSSnapshotConstructor(actor,
                                                  aObject->DocumentURI(),
-                                                 requestedSize,
+                                                 /* increasePeakUsage */ true,
+                                                 /* requestedSize */ 131072,
+                                                 /* minSize */ 4096,
                                                  &initInfo);
   if (NS_WARN_IF(!ok)) {
     return NS_ERROR_FAILURE;
   }
 
   snapshot->SetActor(actor);
 
   // This add refs snapshot.
--- a/dom/localstorage/LSDatabase.h
+++ b/dom/localstorage/LSDatabase.h
@@ -103,17 +103,16 @@ public:
   nsresult
   EndExplicitSnapshot(LSObject* aObject);
 
 private:
   ~LSDatabase();
 
   nsresult
   EnsureSnapshot(LSObject* aObject,
-                 bool aRequestedBySetItem,
                  bool aExplicit = false);
 
   void
   AllowToClose();
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/localstorage/PBackgroundLSDatabase.ipdl
+++ b/dom/localstorage/PBackgroundLSDatabase.ipdl
@@ -43,17 +43,19 @@ parent:
   // error typically causes a crash. The race can be prevented by doing the
   // teardown in two steps. First, we send the DeleteMe message to the parent
   // and the parent then sends the __delete__ message to the child.
   async DeleteMe();
 
   async AllowToClose();
 
   sync PBackgroundLSSnapshot(nsString documentURI,
-                             int64_t requestedSize)
+                             bool increasePeakUsage,
+                             int64_t requestedSize,
+                             int64_t minSize)
     returns (LSSnapshotInitInfo initInfo);
 
 child:
   async __delete__();
 
   async RequestAllowToClose();
 };