Bug 1685677 - Don't unnecessarily materialize a flattened array of OriginInfo*. r=dom-workers-and-storage-reviewers,janv

Differential Revision: https://phabricator.services.mozilla.com/D101151
This commit is contained in:
Simon Giesecke 2021-02-01 13:37:45 +00:00
Родитель 991f534d51
Коммит b9443d148e
3 изменённых файлов: 146 добавлений и 24 удалений

Просмотреть файл

@ -7,6 +7,7 @@
#include "ActorsParent.h"
// Local includes
#include "Flatten.h"
#include "InitializationTypes.h"
#include "OriginScope.h"
#include "QuotaCommon.h"
@ -7115,11 +7116,11 @@ QuotaManager::CollectLRUOriginInfosUntil(Collect&& aCollect, Pred&& aPred) {
return originInfos;
}
QuotaManager::OriginInfosFlatTraversable
QuotaManager::OriginInfosNestedTraversable
QuotaManager::LockedGetOriginInfosExceedingGroupLimit() const {
mQuotaMutex.AssertCurrentThreadOwns();
OriginInfosFlatTraversable originInfos;
OriginInfosNestedTraversable originInfos;
for (const auto& entry : mGroupInfoPairs) {
const auto& pair = entry.GetData();
@ -7146,9 +7147,7 @@ QuotaManager::LockedGetOriginInfosExceedingGroupLimit() const {
MOZ_ASSERT(quotaManager, "Shouldn't be null!");
if (groupUsage > quotaManager->GetGroupLimit()) {
// XXX Instead of appending into a flat array, return an array of
// arrays.
originInfos.AppendElements(CollectLRUOriginInfosUntil(
originInfos.AppendElement(CollectLRUOriginInfosUntil(
[&temporaryGroupInfo, &defaultGroupInfo](auto inserter) {
MaybeInsertOriginInfos(std::move(inserter), temporaryGroupInfo,
defaultGroupInfo,
@ -7170,7 +7169,7 @@ QuotaManager::LockedGetOriginInfosExceedingGroupLimit() const {
QuotaManager::OriginInfosFlatTraversable
QuotaManager::LockedGetOriginInfosExceedingGlobalLimit(
const OriginInfosFlatTraversable& aAlreadyDoomedOriginInfos,
const OriginInfosNestedTraversable& aAlreadyDoomedOriginInfos,
const uint64_t aAlreadyDoomedUsage) const {
mQuotaMutex.AssertCurrentThreadOwns();
@ -7186,7 +7185,13 @@ QuotaManager::LockedGetOriginInfosExceedingGlobalLimit(
inserter, pair->LockedGetGroupInfo(PERSISTENCE_TYPE_TEMPORARY),
pair->LockedGetGroupInfo(PERSISTENCE_TYPE_DEFAULT),
[&aAlreadyDoomedOriginInfos](const auto& originInfo) {
return !aAlreadyDoomedOriginInfos.Contains(originInfo) &&
return !std::any_of(aAlreadyDoomedOriginInfos.cbegin(),
aAlreadyDoomedOriginInfos.cend(),
// XXX This should capture originInfo by
// value, but it can't due to Bug 1421435.
[&originInfo](const auto& array) {
return array.Contains(originInfo);
}) &&
!originInfo->LockedPersisted();
});
}
@ -7203,24 +7208,28 @@ QuotaManager::LockedGetOriginInfosExceedingGlobalLimit(
});
}
QuotaManager::OriginInfosFlatTraversable
QuotaManager::OriginInfosNestedTraversable
QuotaManager::GetOriginInfosExceedingLimits() const {
MutexAutoLock lock(mQuotaMutex);
auto originInfos = LockedGetOriginInfosExceedingGroupLimit();
const uint64_t doomedUsage =
std::accumulate(originInfos.cbegin(), originInfos.cend(), uint64_t(0),
[](uint64_t oldValue, const auto& originInfo) {
return oldValue + originInfo->LockedUsage();
});
const uint64_t doomedUsage = std::accumulate(
originInfos.cbegin(), originInfos.cend(), uint64_t(0),
[](uint64_t oldValue, const auto& currentOriginInfos) {
return std::accumulate(currentOriginInfos.cbegin(),
currentOriginInfos.cend(), oldValue,
[](uint64_t oldValue, const auto& originInfo) {
return oldValue + originInfo->LockedUsage();
});
});
// Evicting origins that exceed their group limit also affects the global
// temporary storage usage. If the global temporary storage limit would still
// be exceeded after evicting the origins that were already selected, we need
// to specifically evict origins to get below the global limit.
if (mTemporaryStorageUsage - doomedUsage > mTemporaryStorageLimit) {
originInfos.AppendElements(
originInfos.AppendElement(
LockedGetOriginInfosExceedingGlobalLimit(originInfos, doomedUsage));
}
@ -7228,13 +7237,12 @@ QuotaManager::GetOriginInfosExceedingLimits() const {
}
void QuotaManager::ClearOrigins(
const OriginInfosFlatTraversable& aDoomedOriginInfos) {
const OriginInfosNestedTraversable& aDoomedOriginInfos) {
AssertIsOnIOThread();
// XXX Does this need to be done a) in order and/or b) sequentially?
// XXX We don't need to concatenate the results of the two steps. It would be
// sufficient to chain the ranges for iteration.
for (const auto& doomedOriginInfo : aDoomedOriginInfos) {
for (const auto& doomedOriginInfo :
Flatten<OriginInfosFlatTraversable::elem_type>(aDoomedOriginInfos)) {
#ifdef DEBUG
{
MutexAutoLock lock(mQuotaMutex);
@ -7249,14 +7257,16 @@ void QuotaManager::ClearOrigins(
{
MutexAutoLock lock(mQuotaMutex);
for (const auto& doomedOriginInfo : aDoomedOriginInfos) {
for (const auto& doomedOriginInfo :
Flatten<OriginInfosFlatTraversable::elem_type>(aDoomedOriginInfos)) {
LockedRemoveQuotaForOrigin(
doomedOriginInfo->mGroupInfo->mPersistenceType,
{doomedOriginInfo->mGroupInfo->mGroup, doomedOriginInfo->mOrigin});
}
}
for (const auto& doomedOriginInfo : aDoomedOriginInfos) {
for (const auto& doomedOriginInfo :
Flatten<OriginInfosFlatTraversable::elem_type>(aDoomedOriginInfos)) {
OriginClearCompleted(doomedOriginInfo->mGroupInfo->mPersistenceType,
doomedOriginInfo->mOrigin, Nullable<Client::Type>());
}

109
dom/quota/Flatten.h Normal file
Просмотреть файл

@ -0,0 +1,109 @@
/* -*- 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/. */
#ifndef DOM_QUOTA_FLATTEN_H_
#define DOM_QUOTA_FLATTEN_H_
#include <iterator>
#include <type_traits>
#include <utility>
// XXX This should be moved to MFBT.
namespace mozilla::dom::quota {
namespace detail {
using std::begin;
using std::end;
template <typename T, typename NestedRange>
auto Flatten(const NestedRange& aRange) -> std::enable_if_t<
std::is_same_v<T, typename decltype(begin(
std::declval<const NestedRange&>()))::value_type>,
const NestedRange&> {
return aRange;
}
template <typename T, typename NestedRange>
struct FlatIter {
using OuterIterator = decltype(begin(std::declval<const NestedRange&>()));
using InnerIterator =
decltype(begin(*begin(std::declval<const NestedRange&>())));
explicit FlatIter(const NestedRange& aRange, OuterIterator aIter)
: mOuterIter{std::move(aIter)}, mOuterEnd{end(aRange)} {
InitInner();
}
const T& operator*() const { return *mInnerIter; }
FlatIter& operator++() {
if (mInnerIter != mInnerEnd) {
++mInnerIter;
} else {
++mOuterIter;
InitInner();
}
return *this;
}
bool operator!=(const FlatIter& aOther) const {
return mOuterIter != aOther.mOuterIter || mInnerIter != aOther.mInnerIter;
}
private:
void InitInner() {
if (mOuterIter != mOuterEnd) {
const auto& innerRange = *mOuterIter;
mInnerIter = begin(innerRange);
mInnerEnd = end(innerRange);
}
}
OuterIterator mOuterIter;
const OuterIterator mOuterEnd;
InnerIterator mInnerIter;
InnerIterator mInnerEnd;
};
template <typename T, typename NestedRange>
struct FlatRange {
explicit FlatRange(const NestedRange& aRange) : mRange{aRange} {}
auto begin() const {
using std::begin;
return FlatIter<T, NestedRange>{mRange, begin(mRange)};
}
auto end() const {
using std::end;
return FlatIter<T, NestedRange>{mRange, end(mRange)};
}
private:
const NestedRange& mRange;
};
template <typename T, typename NestedRange>
auto Flatten(const NestedRange& aRange) -> std::enable_if_t<
!std::is_same_v<T, typename decltype(begin(
std::declval<const NestedRange&>()))::value_type>,
FlatRange<T, NestedRange>> {
return FlatRange<T, NestedRange>{aRange};
}
} // namespace detail
template <typename T, typename NestedRange>
auto Flatten(const NestedRange& aRange) {
return detail::Flatten<T>(aRange);
}
} // namespace mozilla::dom::quota
#endif

Просмотреть файл

@ -563,15 +563,18 @@ class QuotaManager final : public BackgroundThreadObject {
using OriginInfosFlatTraversable =
nsTArray<NotNull<RefPtr<const OriginInfo>>>;
OriginInfosFlatTraversable LockedGetOriginInfosExceedingGroupLimit() const;
using OriginInfosNestedTraversable =
nsTArray<nsTArray<NotNull<RefPtr<const OriginInfo>>>>;
OriginInfosNestedTraversable LockedGetOriginInfosExceedingGroupLimit() const;
OriginInfosFlatTraversable LockedGetOriginInfosExceedingGlobalLimit(
const OriginInfosFlatTraversable& aAlreadyDoomedOriginInfos,
const OriginInfosNestedTraversable& aAlreadyDoomedOriginInfos,
uint64_t aAlreadyDoomedUsage) const;
OriginInfosFlatTraversable GetOriginInfosExceedingLimits() const;
OriginInfosNestedTraversable GetOriginInfosExceedingLimits() const;
void ClearOrigins(const OriginInfosFlatTraversable& aDoomedOriginInfos);
void ClearOrigins(const OriginInfosNestedTraversable& aDoomedOriginInfos);
void CleanupTemporaryStorage();