summaryrefslogtreecommitdiffstats
path: root/dom/media/mediacapabilities/BenchmarkStorageParent.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/mediacapabilities/BenchmarkStorageParent.cpp')
-rw-r--r--dom/media/mediacapabilities/BenchmarkStorageParent.cpp130
1 files changed, 130 insertions, 0 deletions
diff --git a/dom/media/mediacapabilities/BenchmarkStorageParent.cpp b/dom/media/mediacapabilities/BenchmarkStorageParent.cpp
new file mode 100644
index 0000000000..64ae6ddd44
--- /dev/null
+++ b/dom/media/mediacapabilities/BenchmarkStorageParent.cpp
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "BenchmarkStorageParent.h"
+#include "KeyValueStorage.h"
+
+namespace mozilla {
+
+/* Moving average window size. */
+const int32_t AVG_WINDOW = 20;
+/* Calculate the moving average for the new value aValue for the current window
+ * aWindow and the already existing average aAverage. When the method returns
+ * aAverage will contain the new average and aWindow will contain the new
+ * window.*/
+void BenchmarkStorageParent::MovingAverage(int32_t& aAverage, int32_t& aWindow,
+ const int32_t aValue) {
+ if (aWindow < AVG_WINDOW) {
+ aAverage = (aAverage * aWindow + aValue) / (aWindow + 1);
+ aWindow++;
+ return;
+ }
+ MOZ_ASSERT(aWindow == AVG_WINDOW);
+ aAverage = (aAverage - aAverage / aWindow) + (aValue / aWindow);
+}
+
+/* In order to decrease the number of times the database is accessed when the
+ * moving average is stored or retrieved we use the same value to store _both_
+ * the window and the average. The range of the average is limited since it is
+ * a percentage (0-100), and the range of the window is limited
+ * (1-20). Thus the number that is stored in the database is in the form
+ * (digits): WWAAA. For example, the value stored when an average(A) of 88
+ * corresponds to a window(W) 7 is 7088. The average of 100 that corresponds to
+ * a window of 20 is 20100. The following methods are helpers to extract or
+ * construct the stored value according to the above. */
+
+/* Stored value will be in the form WWAAA(19098). We need to extract the window
+ * (19) and the average score (98). The aValue will
+ * be parsed, the aWindow will contain the window (of the moving average) and
+ * the return value will contain the average itself. */
+int32_t BenchmarkStorageParent::ParseStoredValue(int32_t aValue,
+ int32_t& aWindow) {
+ MOZ_ASSERT(aValue > 999);
+ MOZ_ASSERT(aValue < 100000);
+
+ int32_t score = aValue % 1000;
+ aWindow = (aValue / 1000) % 100;
+ return score;
+}
+
+int32_t BenchmarkStorageParent::PrepareStoredValue(int32_t aScore,
+ int32_t aWindow) {
+ MOZ_ASSERT(aScore >= 0);
+ MOZ_ASSERT(aScore <= 100);
+ MOZ_ASSERT(aWindow > 0);
+ MOZ_ASSERT(aWindow < 21);
+
+ return aWindow * 1000 + aScore;
+}
+
+BenchmarkStorageParent::BenchmarkStorageParent()
+ : mStorage(new KeyValueStorage) {}
+
+IPCResult BenchmarkStorageParent::RecvPut(const nsCString& aDbName,
+ const nsCString& aKey,
+ const int32_t& aValue) {
+ // In order to calculate and store the new moving average, we need to get the
+ // stored value and window first, to calculate the new score and window, and
+ // then to store the new aggregated value.
+ mStorage->Get(aDbName, aKey)
+ ->Then(
+ GetCurrentSerialEventTarget(), __func__,
+ [storage = mStorage, aDbName, aKey, aValue](int32_t aResult) {
+ int32_t window = 0;
+ int32_t average = 0;
+ if (aResult >= 0) {
+ // The key found.
+ average = ParseStoredValue(aResult, window);
+ }
+ MovingAverage(average, window, aValue);
+ int32_t newValue = PrepareStoredValue(average, window);
+ // Avoid storing if the values are the same. This is an optimization
+ // to minimize the disk usage.
+ if (aResult != newValue) {
+ storage->Put(aDbName, aKey, newValue);
+ }
+ },
+ [](nsresult rv) { /*do nothing*/ });
+
+ return IPC_OK();
+}
+
+IPCResult BenchmarkStorageParent::RecvGet(const nsCString& aDbName,
+ const nsCString& aKey,
+ GetResolver&& aResolve) {
+ mStorage->Get(aDbName, aKey)
+ ->Then(
+ GetCurrentSerialEventTarget(), __func__,
+ [aResolve](int32_t aResult) {
+ int32_t window = 0; // not used
+ aResolve(aResult < 0 ? -1 : ParseStoredValue(aResult, window));
+ },
+ [aResolve](nsresult rv) { aResolve(-1); });
+
+ return IPC_OK();
+}
+
+IPCResult BenchmarkStorageParent::RecvCheckVersion(const nsCString& aDbName,
+ int32_t aVersion) {
+ mStorage->Get(aDbName, "Version"_ns)
+ ->Then(
+ GetCurrentSerialEventTarget(), __func__,
+ [storage = mStorage, aDbName, aVersion](int32_t aResult) {
+ if (aVersion != aResult) {
+ storage->Clear(aDbName)->Then(
+ GetCurrentSerialEventTarget(), __func__,
+ [storage, aDbName, aVersion](bool) {
+ storage->Put(aDbName, "Version"_ns, aVersion);
+ },
+ [](nsresult rv) { /*do nothing*/ });
+ }
+ },
+ [](nsresult rv) { /*do nothing*/ });
+
+ return IPC_OK();
+}
+
+}; // namespace mozilla