зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1540573 - P4. Use larger MediaCache sizes when on cellular connection. r=jya
Differential Revision: https://phabricator.services.mozilla.com/D26233 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
8ad76b6460
Коммит
217bd1680c
|
@ -125,11 +125,9 @@ void FileBlockCache::Flush() {
|
|||
}));
|
||||
}
|
||||
|
||||
int32_t FileBlockCache::GetMaxBlocks() const {
|
||||
size_t FileBlockCache::GetMaxBlocks(size_t aCacheSizeInKB) const {
|
||||
// We look up the cache size every time. This means dynamic changes
|
||||
// to the pref are applied.
|
||||
const uint32_t cacheSizeKb =
|
||||
std::min(StaticPrefs::MediaCacheSize(), uint32_t(INT32_MAX) * 2);
|
||||
// Ensure we can divide BLOCK_SIZE by 1024.
|
||||
static_assert(MediaCacheStream::BLOCK_SIZE % 1024 == 0,
|
||||
"BLOCK_SIZE should be a multiple of 1024");
|
||||
|
@ -140,14 +138,13 @@ int32_t FileBlockCache::GetMaxBlocks() const {
|
|||
static_assert(MediaCacheStream::BLOCK_SIZE / 1024 <= int64_t(UINT32_MAX),
|
||||
"BLOCK_SIZE / 1024 should be at most UINT32_MAX");
|
||||
// Since BLOCK_SIZE is a strict multiple of 1024,
|
||||
// cacheSizeKb * 1024 / BLOCK_SIZE == cacheSizeKb / (BLOCK_SIZE / 1024),
|
||||
// but the latter formula avoids a potential overflow from `* 1024`.
|
||||
// aCacheSizeInKB * 1024 / BLOCK_SIZE == aCacheSizeInKB / (BLOCK_SIZE /
|
||||
// 1024), but the latter formula avoids a potential overflow from `* 1024`.
|
||||
// And because BLOCK_SIZE/1024 is at least 2, the maximum cache size
|
||||
// INT32_MAX*2 will give a maxBlocks that can fit in an int32_t.
|
||||
constexpr uint32_t blockSizeKb =
|
||||
uint32_t(MediaCacheStream::BLOCK_SIZE / 1024);
|
||||
const int32_t maxBlocks = int32_t(cacheSizeKb / blockSizeKb);
|
||||
return std::max(maxBlocks, int32_t(1));
|
||||
constexpr size_t blockSizeKb = size_t(MediaCacheStream::BLOCK_SIZE / 1024);
|
||||
const size_t maxBlocks = aCacheSizeInKB / blockSizeKb;
|
||||
return std::max(maxBlocks, size_t(1));
|
||||
}
|
||||
|
||||
FileBlockCache::FileBlockCache()
|
||||
|
|
|
@ -68,7 +68,7 @@ class FileBlockCache : public MediaBlockCacheBase {
|
|||
|
||||
// Maximum number of blocks allowed in this block cache.
|
||||
// Calculated from "media.cache_size" pref.
|
||||
int32_t GetMaxBlocks() const override;
|
||||
size_t GetMaxBlocks(size_t aCacheSizeInKB) const override;
|
||||
|
||||
// Can be called on any thread. This defers to a non-main thread.
|
||||
nsresult WriteBlock(uint32_t aBlockIndex, Span<const uint8_t> aData1,
|
||||
|
|
|
@ -56,7 +56,7 @@ class MediaBlockCacheBase {
|
|||
|
||||
// Maximum number of blocks expected in this block cache. (But allow overflow
|
||||
// to accomodate incoming traffic before MediaCache can handle it.)
|
||||
virtual int32_t GetMaxBlocks() const = 0;
|
||||
virtual size_t GetMaxBlocks(size_t aCacheSizeInKiB) const = 0;
|
||||
|
||||
// Can be called on any thread. This defers to a non-main thread.
|
||||
virtual nsresult WriteBlock(uint32_t aBlockIndex, Span<const uint8_t> aData1,
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "MediaBlockCacheBase.h"
|
||||
#include "MediaResource.h"
|
||||
#include "MemoryBlockCache.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/ErrorNames.h"
|
||||
|
@ -23,12 +24,14 @@
|
|||
#include "mozilla/SystemGroup.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsINetworkLinkService.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "prio.h"
|
||||
#include "VideoUtils.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -114,7 +117,6 @@ void MediaCacheFlusher::RegisterMediaCache(MediaCache* aMediaCache) {
|
|||
|
||||
if (!gMediaCacheFlusher) {
|
||||
gMediaCacheFlusher = new MediaCacheFlusher();
|
||||
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
if (observerService) {
|
||||
|
@ -122,6 +124,10 @@ void MediaCacheFlusher::RegisterMediaCache(MediaCache* aMediaCache) {
|
|||
true);
|
||||
observerService->AddObserver(gMediaCacheFlusher,
|
||||
"cacheservice:empty-cache", true);
|
||||
observerService->AddObserver(
|
||||
gMediaCacheFlusher, "contentchild:network-link-type-changed", true);
|
||||
observerService->AddObserver(gMediaCacheFlusher,
|
||||
NS_NETWORK_LINK_TYPE_TOPIC, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,6 +248,10 @@ class MediaCache {
|
|||
return mMonitor;
|
||||
}
|
||||
|
||||
// Updates the cache size, readahead limit, and resume threshold, based on
|
||||
// whether we're on a cellular connection or not. Main thread only.
|
||||
static void UpdateGeometryStatics();
|
||||
|
||||
/**
|
||||
* An iterator that makes it easy to iterate through all streams that
|
||||
* have a given resource ID and are not closed.
|
||||
|
@ -282,6 +292,7 @@ class MediaCache {
|
|||
NS_ASSERTION(NS_IsMainThread(), "Only construct MediaCache on main thread");
|
||||
MOZ_COUNT_CTOR(MediaCache);
|
||||
MediaCacheFlusher::RegisterMediaCache(this);
|
||||
UpdateGeometryStatics();
|
||||
}
|
||||
|
||||
~MediaCache() {
|
||||
|
@ -313,6 +324,21 @@ class MediaCache {
|
|||
MOZ_COUNT_DTOR(MediaCache);
|
||||
}
|
||||
|
||||
static size_t CacheSize() {
|
||||
MOZ_ASSERT(sThread->IsOnCurrentThread());
|
||||
return sCacheSizeInKB;
|
||||
}
|
||||
|
||||
static size_t ReadaheadLimit() {
|
||||
MOZ_ASSERT(sThread->IsOnCurrentThread());
|
||||
return sReadaheadLimit;
|
||||
}
|
||||
|
||||
static size_t ResumeThreshold() {
|
||||
MOZ_ASSERT(sThread->IsOnCurrentThread());
|
||||
return sResumeThreshold;
|
||||
}
|
||||
|
||||
// Find a free or reusable block and return its index. If there are no
|
||||
// free blocks and no reusable blocks, add a new block to the cache
|
||||
// and return it. Can return -1 on OOM.
|
||||
|
@ -451,6 +477,11 @@ class MediaCache {
|
|||
// to access sThread on all threads.
|
||||
static bool sThreadInit;
|
||||
|
||||
// Accesson MediaCache thread only.
|
||||
static size_t sCacheSizeInKB;
|
||||
static size_t sReadaheadLimit;
|
||||
static size_t sResumeThreshold;
|
||||
|
||||
private:
|
||||
// Used by MediaCacheStream::GetDebugInfo() only for debugging.
|
||||
// Don't add new callers to this function.
|
||||
|
@ -470,6 +501,37 @@ StaticRefPtr<nsIThread> MediaCache::sThread;
|
|||
/* static */
|
||||
bool MediaCache::sThreadInit = false;
|
||||
|
||||
/* static */ size_t MediaCache::sCacheSizeInKB = 0;
|
||||
/* static */ size_t MediaCache::sReadaheadLimit = 0;
|
||||
/* static */ size_t MediaCache::sResumeThreshold = 0;
|
||||
|
||||
void MediaCache::UpdateGeometryStatics() {
|
||||
NS_ASSERTION(NS_IsMainThread(),
|
||||
"Only call on main thread"); // JNI required on Android...
|
||||
bool cacheAggressively = !OnCellularConnection();
|
||||
LOG("MediaCache::UpdateGeometryStatics() cacheAggressively=%d",
|
||||
cacheAggressively);
|
||||
// Read the prefs on the main thread, and post their value to the MediaCache
|
||||
// thread. This ensures the values are synchronized.
|
||||
uint32_t cacheSize = 0, readaheadLimit = 0, resumeThreshold = 0;
|
||||
if (cacheAggressively) {
|
||||
cacheSize = StaticPrefs::MediaCacheSize();
|
||||
readaheadLimit = StaticPrefs::MediaCacheReadaheadLimit();
|
||||
resumeThreshold = StaticPrefs::MediaCacheResumeThreshold();
|
||||
} else {
|
||||
cacheSize = StaticPrefs::MediaCacheCellularSize();
|
||||
readaheadLimit = StaticPrefs::MediaCacheCellularReadaheadLimit();
|
||||
resumeThreshold = StaticPrefs::MediaCacheCellularResumeThreshold();
|
||||
}
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NS_NewRunnableFunction("MediaCache::UpdateGeometryStatics", [=]() {
|
||||
sCacheSizeInKB = cacheSize;
|
||||
sReadaheadLimit = readaheadLimit;
|
||||
sResumeThreshold = resumeThreshold;
|
||||
});
|
||||
sThread->Dispatch(r.forget());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MediaCacheFlusher::Observe(nsISupports* aSubject, char const* aTopic,
|
||||
char16_t const* aData) {
|
||||
|
@ -487,6 +549,10 @@ MediaCacheFlusher::Observe(nsISupports* aSubject, char const* aTopic,
|
|||
}
|
||||
return NS_OK;
|
||||
}
|
||||
if (strcmp(aTopic, "contentchild:network-link-type-changed") == 0 ||
|
||||
strcmp(aTopic, NS_NETWORK_LINK_TYPE_TOPIC) == 0) {
|
||||
MediaCache::UpdateGeometryStatics();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -827,7 +893,8 @@ int32_t MediaCache::FindBlockForIncomingData(AutoLock& aLock, TimeStamp aNow,
|
|||
// b) the data we're going to store in the free block is not higher
|
||||
// priority than the data already stored in the free block.
|
||||
// The latter can lead us to go over the cache limit a bit.
|
||||
if ((mIndex.Length() < uint32_t(mBlockCache->GetMaxBlocks()) ||
|
||||
if ((mIndex.Length() <
|
||||
uint32_t(mBlockCache->GetMaxBlocks(MediaCache::CacheSize())) ||
|
||||
blockIndex < 0 ||
|
||||
PredictNextUseForIncomingData(aLock, aStream) >=
|
||||
PredictNextUse(aLock, aNow, blockIndex))) {
|
||||
|
@ -1155,7 +1222,7 @@ void MediaCache::Update() {
|
|||
mInUpdate = true;
|
||||
#endif
|
||||
|
||||
int32_t maxBlocks = mBlockCache->GetMaxBlocks();
|
||||
int32_t maxBlocks = mBlockCache->GetMaxBlocks(MediaCache::CacheSize());
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
|
||||
int32_t freeBlockCount = mFreeBlocks.GetCount();
|
||||
|
@ -1276,8 +1343,8 @@ void MediaCache::Update() {
|
|||
}
|
||||
}
|
||||
|
||||
int32_t resumeThreshold = StaticPrefs::MediaCacheResumeThreshold();
|
||||
int32_t readaheadLimit = StaticPrefs::MediaCacheReadaheadLimit();
|
||||
int32_t resumeThreshold = MediaCache::ResumeThreshold();
|
||||
int32_t readaheadLimit = MediaCache::ReadaheadLimit();
|
||||
|
||||
for (uint32_t i = 0; i < mStreams.Length(); ++i) {
|
||||
actions.AppendElement(StreamAction{});
|
||||
|
|
|
@ -45,7 +45,7 @@ class MemoryBlockCache : public MediaBlockCacheBase {
|
|||
|
||||
// Maximum number of blocks allowed in this block cache.
|
||||
// Based on initial content length, and minimum usable block cache.
|
||||
int32_t GetMaxBlocks() const override { return mMaxBlocks; }
|
||||
size_t GetMaxBlocks(size_t) const override { return mMaxBlocks; }
|
||||
|
||||
// Can be called on any thread.
|
||||
virtual nsresult WriteBlock(uint32_t aBlockIndex, Span<const uint8_t> aData1,
|
||||
|
@ -73,7 +73,7 @@ class MemoryBlockCache : public MediaBlockCacheBase {
|
|||
const size_t mInitialContentLength;
|
||||
|
||||
// Maximum number of blocks that this MemoryBlockCache expects.
|
||||
const int32_t mMaxBlocks;
|
||||
const size_t mMaxBlocks;
|
||||
|
||||
// Mutex which controls access to all members below.
|
||||
Mutex mMutex;
|
||||
|
|
|
@ -1441,17 +1441,18 @@ VARCACHE_PREF(
|
|||
// reviewer had an unshakeable preference for that.
|
||||
|
||||
// File-backed MediaCache size.
|
||||
#ifdef ANDROID
|
||||
# define PREF_VALUE 32768 // Measured in KiB
|
||||
#else
|
||||
# define PREF_VALUE 512000 // Measured in KiB
|
||||
#endif
|
||||
VARCACHE_PREF(
|
||||
"media.cache_size",
|
||||
MediaCacheSize,
|
||||
RelaxedAtomicUint32, PREF_VALUE
|
||||
uint32_t, 512000 // Measured in KiB
|
||||
)
|
||||
// Size of file backed MediaCache while on a connection which is cellular (3G, etc),
|
||||
// and thus assumed to be "expensive".
|
||||
VARCACHE_PREF(
|
||||
"media.cache_size.cellular",
|
||||
MediaCacheCellularSize,
|
||||
uint32_t, 32768 // Measured in KiB
|
||||
)
|
||||
#undef PREF_VALUE
|
||||
|
||||
// If a resource is known to be smaller than this size (in kilobytes), a
|
||||
// memory-backed MediaCache may be used; otherwise the (single shared global)
|
||||
|
@ -1480,32 +1481,30 @@ VARCACHE_PREF(
|
|||
|
||||
// When a network connection is suspended, don't resume it until the amount of
|
||||
// buffered data falls below this threshold (in seconds).
|
||||
#ifdef ANDROID
|
||||
# define PREF_VALUE 10 // Use a smaller limit to save battery.
|
||||
#else
|
||||
# define PREF_VALUE 30
|
||||
#endif
|
||||
VARCACHE_PREF(
|
||||
"media.cache_resume_threshold",
|
||||
MediaCacheResumeThreshold,
|
||||
RelaxedAtomicInt32, PREF_VALUE
|
||||
uint32_t, 30
|
||||
)
|
||||
VARCACHE_PREF(
|
||||
"media.cache_resume_threshold.cellular",
|
||||
MediaCacheCellularResumeThreshold,
|
||||
uint32_t, 10
|
||||
)
|
||||
#undef PREF_VALUE
|
||||
|
||||
// Stop reading ahead when our buffered data is this many seconds ahead of the
|
||||
// current playback position. This limit can stop us from using arbitrary
|
||||
// amounts of network bandwidth prefetching huge videos.
|
||||
#ifdef ANDROID
|
||||
# define PREF_VALUE 30 // Use a smaller limit to save battery.
|
||||
#else
|
||||
# define PREF_VALUE 60
|
||||
#endif
|
||||
VARCACHE_PREF(
|
||||
"media.cache_readahead_limit",
|
||||
MediaCacheReadaheadLimit,
|
||||
RelaxedAtomicInt32, PREF_VALUE
|
||||
uint32_t, 60
|
||||
)
|
||||
VARCACHE_PREF(
|
||||
"media.cache_readahead_limit.cellular",
|
||||
MediaCacheCellularReadaheadLimit,
|
||||
uint32_t, 30
|
||||
)
|
||||
#undef PREF_VALUE
|
||||
|
||||
// AudioSink
|
||||
VARCACHE_PREF(
|
||||
|
|
Загрузка…
Ссылка в новой задаче