Bug 1286798 - Part 39: Reduce number of hash lookups; r=asuth
authorJan Varga <jan.varga@gmail.com>
Thu, 29 Nov 2018 21:49:20 +0100
changeset 508037 4f699604c96059b4f198c2b2b8e12f3b3196d3cc
parent 508036 ef64949fc1aa9e951bcbd0facbd8309ef7ccabf9
child 508038 f2cdc8e4ef39643e4d3930544ecde4b690c3e326
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 39: Reduce number of hash lookups; r=asuth
dom/localstorage/LSSnapshot.cpp
dom/localstorage/LSSnapshot.h
--- a/dom/localstorage/LSSnapshot.cpp
+++ b/dom/localstorage/LSSnapshot.cpp
@@ -153,84 +153,19 @@ LSSnapshot::GetItem(const nsAString& aKe
                     nsAString& aResult)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mActor);
   MOZ_ASSERT(mInitialized);
   MOZ_ASSERT(!mSentFinish);
 
   nsString result;
-
-  switch (mLoadState) {
-    case LoadState::Partial: {
-      if (mValues.Get(aKey, &result)) {
-        MOZ_ASSERT(!result.IsVoid());
-      } else if (mLoadedItems.GetEntry(aKey) || mUnknownItems.GetEntry(aKey)) {
-        result.SetIsVoid(true);
-      } else {
-        if (NS_WARN_IF(!mActor->SendLoadItem(nsString(aKey), &result))) {
-          return NS_ERROR_FAILURE;
-        }
-
-        if (result.IsVoid()) {
-          mUnknownItems.PutEntry(aKey);
-        } else {
-          mLoadedItems.PutEntry(aKey);
-          mValues.Put(aKey, result);
-
-          if (mLoadedItems.Count() == mInitLength) {
-            mLoadedItems.Clear();
-            mUnknownItems.Clear();
-            mLength = 0;
-            mLoadState = LoadState::AllUnorderedItems;
-          }
-        }
-      }
-
-      break;
-    }
-
-    case LoadState::AllOrderedKeys: {
-      if (mValues.Get(aKey, &result)) {
-        if (result.IsVoid()) {
-          if (NS_WARN_IF(!mActor->SendLoadItem(nsString(aKey), &result))) {
-            return NS_ERROR_FAILURE;
-          }
-
-          MOZ_ASSERT(!result.IsVoid());
-
-          mLoadedItems.PutEntry(aKey);
-          mValues.Put(aKey, result);
-
-          if (mLoadedItems.Count() == mInitLength) {
-            mLoadedItems.Clear();
-            MOZ_ASSERT(mLength == 0);
-            mLoadState = LoadState::AllOrderedItems;
-          }
-        }
-      } else {
-        result.SetIsVoid(true);
-      }
-
-      break;
-    }
-
-    case LoadState::AllUnorderedItems:
-    case LoadState::AllOrderedItems: {
-      if (mValues.Get(aKey, &result)) {
-        MOZ_ASSERT(!result.IsVoid());
-      } else {
-        result.SetIsVoid(true);
-      }
-
-      break;
-    }
-
-    default:
-      MOZ_CRASH("Bad state!");
+  nsresult rv = GetItemInternal(aKey, Optional<nsString>(), result);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
   }
 
   aResult = result;
   return NS_OK;
 }
 
 nsresult
 LSSnapshot::GetKeys(nsTArray<nsString>& aKeys)
@@ -258,17 +193,18 @@ LSSnapshot::SetItem(const nsAString& aKe
                     LSNotifyInfo& aNotifyInfo)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mActor);
   MOZ_ASSERT(mInitialized);
   MOZ_ASSERT(!mSentFinish);
 
   nsString oldValue;
-  nsresult rv = GetItem(aKey, oldValue);
+  nsresult rv =
+    GetItemInternal(aKey, Optional<nsString>(nsString(aValue)), oldValue);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   bool changed;
   if (oldValue == aValue && oldValue.IsVoid() == aValue.IsVoid()) {
     changed = false;
   } else {
@@ -278,21 +214,24 @@ LSSnapshot::SetItem(const nsAString& aKe
                     static_cast<int64_t>(oldValue.Length());
 
     if (oldValue.IsVoid()) {
       delta += static_cast<int64_t>(aKey.Length());
     }
 
     rv = UpdateUsage(delta);
     if (NS_WARN_IF(NS_FAILED(rv))) {
+      if (oldValue.IsVoid()) {
+        mValues.Remove(aKey);
+      } else {
+        mValues.Put(aKey, oldValue);
+      }
       return rv;
     }
 
-    mValues.Put(aKey, nsString(aValue));
-
     if (oldValue.IsVoid() && mLoadState == LoadState::Partial) {
       mLength++;
     }
 
     LSSetItemInfo setItemInfo;
     setItemInfo.key() = aKey;
     setItemInfo.oldValue() = oldValue;
     setItemInfo.value() = aValue;
@@ -311,35 +250,34 @@ LSSnapshot::RemoveItem(const nsAString& 
                        LSNotifyInfo& aNotifyInfo)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mActor);
   MOZ_ASSERT(mInitialized);
   MOZ_ASSERT(!mSentFinish);
 
   nsString oldValue;
-  nsresult rv = GetItem(aKey, oldValue);
+  nsresult rv =
+    GetItemInternal(aKey, Optional<nsString>(VoidString()), oldValue);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   bool changed;
   if (oldValue.IsVoid()) {
     changed = false;
   } else {
     changed = true;
 
     int64_t delta = -(static_cast<int64_t>(aKey.Length()) +
                       static_cast<int64_t>(oldValue.Length()));
 
     DebugOnly<nsresult> rv = UpdateUsage(delta);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
 
-    mValues.Remove(aKey);
-
     if (mLoadState == LoadState::Partial) {
       mLength--;
     }
 
     LSRemoveItemInfo removeItemInfo;
     removeItemInfo.key() = aKey;
     removeItemInfo.oldValue() = oldValue;
 
@@ -424,16 +362,141 @@ LSSnapshot::Finish()
   } else {
     MOZ_ASSERT(!mSelfRef);
   }
 
   return NS_OK;
 }
 
 nsresult
+LSSnapshot::GetItemInternal(const nsAString& aKey,
+                            const Optional<nsString>& aValue,
+                            nsAString& aResult)
+{
+  AssertIsOnOwningThread();
+  MOZ_ASSERT(mActor);
+  MOZ_ASSERT(mInitialized);
+  MOZ_ASSERT(!mSentFinish);
+
+  nsString result;
+
+  switch (mLoadState) {
+    case LoadState::Partial: {
+      if (mValues.Get(aKey, &result)) {
+        MOZ_ASSERT(!result.IsVoid());
+      } else if (mLoadedItems.GetEntry(aKey) || mUnknownItems.GetEntry(aKey)) {
+        result.SetIsVoid(true);
+      } else {
+        if (NS_WARN_IF(!mActor->SendLoadItem(nsString(aKey), &result))) {
+          return NS_ERROR_FAILURE;
+        }
+
+        if (result.IsVoid()) {
+          mUnknownItems.PutEntry(aKey);
+        } else {
+          mLoadedItems.PutEntry(aKey);
+          mValues.Put(aKey, result);
+
+          if (mLoadedItems.Count() == mInitLength) {
+            mLoadedItems.Clear();
+            mUnknownItems.Clear();
+            mLength = 0;
+            mLoadState = LoadState::AllUnorderedItems;
+          }
+        }
+      }
+
+      if (aValue.WasPassed()) {
+        const nsString& value = aValue.Value();
+        if (!value.IsVoid()) {
+          mValues.Put(aKey, value);
+        } else if (!result.IsVoid()) {
+          mValues.Remove(aKey);
+        }
+      }
+
+      break;
+    }
+
+    case LoadState::AllOrderedKeys: {
+      if (mValues.Get(aKey, &result)) {
+        if (result.IsVoid()) {
+          if (NS_WARN_IF(!mActor->SendLoadItem(nsString(aKey), &result))) {
+            return NS_ERROR_FAILURE;
+          }
+
+          MOZ_ASSERT(!result.IsVoid());
+
+          mLoadedItems.PutEntry(aKey);
+          mValues.Put(aKey, result);
+
+          if (mLoadedItems.Count() == mInitLength) {
+            mLoadedItems.Clear();
+            MOZ_ASSERT(mLength == 0);
+            mLoadState = LoadState::AllOrderedItems;
+          }
+        }
+      } else {
+        result.SetIsVoid(true);
+      }
+
+      if (aValue.WasPassed()) {
+        const nsString& value = aValue.Value();
+        if (!value.IsVoid()) {
+          mValues.Put(aKey, value);
+        } else if (!result.IsVoid()) {
+          mValues.Remove(aKey);
+        }
+      }
+
+      break;
+    }
+
+    case LoadState::AllUnorderedItems:
+    case LoadState::AllOrderedItems: {
+      if (aValue.WasPassed()) {
+        const nsString& value = aValue.Value();
+        if (!value.IsVoid()) {
+          auto entry = mValues.LookupForAdd(aKey);
+          if (entry) {
+            result = entry.Data();
+            entry.Data() = value;
+          } else {
+            result.SetIsVoid(true);
+            entry.OrInsert([value]() { return value; });
+          }
+        } else {
+          if (auto entry = mValues.Lookup(aKey)) {
+            result = entry.Data();
+            MOZ_ASSERT(!result.IsVoid());
+            entry.Remove();
+          } else {
+            result.SetIsVoid(true);
+          }
+        }
+      } else {
+        if (mValues.Get(aKey, &result)) {
+          MOZ_ASSERT(!result.IsVoid());
+        } else {
+          result.SetIsVoid(true);
+        }
+      }
+
+      break;
+    }
+
+    default:
+      MOZ_CRASH("Bad state!");
+  }
+
+  aResult = result;
+  return NS_OK;
+}
+
+nsresult
 LSSnapshot::EnsureAllKeys()
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mActor);
   MOZ_ASSERT(mInitialized);
   MOZ_ASSERT(!mSentFinish);
   MOZ_ASSERT(mLoadState != LoadState::Initial);
 
--- a/dom/localstorage/LSSnapshot.h
+++ b/dom/localstorage/LSSnapshot.h
@@ -115,16 +115,21 @@ public:
 
   nsresult
   Finish();
 
 private:
   ~LSSnapshot();
 
   nsresult
+  GetItemInternal(const nsAString& aKey,
+                  const Optional<nsString>& aValue,
+                  nsAString& aResult);
+
+  nsresult
   EnsureAllKeys();
 
   nsresult
   UpdateUsage(int64_t aDelta);
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIRUNNABLE
 };