mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-21 01:05:45 +00:00
Bug 1241096 - Add a better memory reporting system for AudioBuffers. r=erahm
MozReview-Commit-ID: GHiauyyD3R2
This commit is contained in:
parent
b1378bc5e8
commit
2b277c167c
@ -12,6 +12,7 @@
|
||||
#include "AudioChannelFormat.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "AudioNodeEngine.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -39,6 +40,128 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AudioBuffer, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AudioBuffer, Release)
|
||||
|
||||
/**
|
||||
* AudioBuffers can be shared between AudioContexts, so we need a separate
|
||||
* mechanism to track their memory usage. This thread-safe class keeps track of
|
||||
* all the AudioBuffers, and gets called back by the memory reporting system
|
||||
* when a memory report is needed, reporting how much memory is used by the
|
||||
* buffers backing AudioBuffer objects. */
|
||||
class AudioBufferMemoryTracker : public nsIMemoryReporter
|
||||
{
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIMEMORYREPORTER
|
||||
|
||||
private:
|
||||
AudioBufferMemoryTracker();
|
||||
virtual ~AudioBufferMemoryTracker();
|
||||
|
||||
public:
|
||||
/* Those methods can be called on any thread. */
|
||||
static void RegisterAudioBuffer(const AudioBuffer* aAudioBuffer);
|
||||
static void UnregisterAudioBuffer(const AudioBuffer* aAudioBuffer);
|
||||
static AudioBufferMemoryTracker* GetInstance();
|
||||
private:
|
||||
/* Those methods must be called with the lock held. */
|
||||
void RegisterAudioBufferInternal(const AudioBuffer* aAudioBuffer);
|
||||
/* Returns the number of buffers still present in the hash table. */
|
||||
uint32_t UnregisterAudioBufferInternal(const AudioBuffer* aAudioBuffer);
|
||||
void Init();
|
||||
|
||||
/* This protects all members of this class. */
|
||||
static StaticMutex sMutex;
|
||||
static StaticRefPtr<AudioBufferMemoryTracker> sSingleton;
|
||||
nsTHashtable<nsPtrHashKey<const AudioBuffer>> mBuffers;
|
||||
};
|
||||
|
||||
StaticRefPtr<AudioBufferMemoryTracker> AudioBufferMemoryTracker::sSingleton;
|
||||
StaticMutex AudioBufferMemoryTracker::sMutex;
|
||||
|
||||
NS_IMPL_ISUPPORTS(AudioBufferMemoryTracker, nsIMemoryReporter);
|
||||
|
||||
AudioBufferMemoryTracker* AudioBufferMemoryTracker::GetInstance()
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (!sSingleton) {
|
||||
sSingleton = new AudioBufferMemoryTracker();
|
||||
sSingleton->Init();
|
||||
}
|
||||
return sSingleton;
|
||||
}
|
||||
|
||||
AudioBufferMemoryTracker::AudioBufferMemoryTracker()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
AudioBufferMemoryTracker::Init()
|
||||
{
|
||||
RegisterWeakMemoryReporter(this);
|
||||
}
|
||||
|
||||
AudioBufferMemoryTracker::~AudioBufferMemoryTracker()
|
||||
{
|
||||
UnregisterWeakMemoryReporter(this);
|
||||
}
|
||||
|
||||
void
|
||||
AudioBufferMemoryTracker::RegisterAudioBuffer(const AudioBuffer* aAudioBuffer)
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
AudioBufferMemoryTracker* tracker = AudioBufferMemoryTracker::GetInstance();
|
||||
tracker->RegisterAudioBufferInternal(aAudioBuffer);
|
||||
}
|
||||
|
||||
void
|
||||
AudioBufferMemoryTracker::UnregisterAudioBuffer(const AudioBuffer* aAudioBuffer)
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
AudioBufferMemoryTracker* tracker = AudioBufferMemoryTracker::GetInstance();
|
||||
uint32_t count;
|
||||
count = tracker->UnregisterAudioBufferInternal(aAudioBuffer);
|
||||
if (count == 0) {
|
||||
sSingleton = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioBufferMemoryTracker::RegisterAudioBufferInternal(const AudioBuffer* aAudioBuffer)
|
||||
{
|
||||
sMutex.AssertCurrentThreadOwns();
|
||||
mBuffers.PutEntry(aAudioBuffer);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
AudioBufferMemoryTracker::UnregisterAudioBufferInternal(const AudioBuffer* aAudioBuffer)
|
||||
{
|
||||
sMutex.AssertCurrentThreadOwns();
|
||||
mBuffers.RemoveEntry(aAudioBuffer);
|
||||
return mBuffers.Count();
|
||||
}
|
||||
|
||||
MOZ_DEFINE_MALLOC_SIZE_OF(AudioBufferMemoryTrackerMallocSizeOf)
|
||||
|
||||
NS_IMETHODIMP
|
||||
AudioBufferMemoryTracker::CollectReports(nsIHandleReportCallback* handleReport,
|
||||
nsISupports* data, bool)
|
||||
{
|
||||
size_t amount = 0;
|
||||
nsresult rv;
|
||||
|
||||
for (auto iter = mBuffers.Iter(); !iter.Done(); iter.Next()) {
|
||||
amount += iter.Get()->GetKey()->SizeOfIncludingThis(AudioBufferMemoryTrackerMallocSizeOf);
|
||||
}
|
||||
|
||||
rv = handleReport->Callback(EmptyCString(),
|
||||
NS_LITERAL_CSTRING("explicit/webaudio/audiobuffer"),
|
||||
KIND_HEAP, UNITS_BYTES, amount,
|
||||
NS_LITERAL_CSTRING("Memory used by AudioBuffer"
|
||||
" objects (Web Audio)"),
|
||||
data);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
AudioBuffer::AudioBuffer(AudioContext* aContext, uint32_t aNumberOfChannels,
|
||||
uint32_t aLength, float aSampleRate,
|
||||
already_AddRefed<ThreadSharedFloatArrayBufferList>
|
||||
@ -52,10 +175,12 @@ AudioBuffer::AudioBuffer(AudioContext* aContext, uint32_t aNumberOfChannels,
|
||||
mSharedChannels->GetChannels() == aNumberOfChannels);
|
||||
mJSChannels.SetLength(aNumberOfChannels);
|
||||
mozilla::HoldJSObjects(this);
|
||||
AudioBufferMemoryTracker::GetInstance()->RegisterAudioBuffer(this);
|
||||
}
|
||||
|
||||
AudioBuffer::~AudioBuffer()
|
||||
{
|
||||
AudioBufferMemoryTracker::GetInstance()->UnregisterAudioBuffer(this);
|
||||
ClearJSChannels();
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsTArray.h"
|
||||
#include "AudioContext.h"
|
||||
|
@ -615,9 +615,8 @@ size_t
|
||||
AudioBufferSourceNode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
size_t amount = AudioNode::SizeOfExcludingThis(aMallocSizeOf);
|
||||
if (mBuffer) {
|
||||
amount += mBuffer->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
/* mBuffer can be shared and is accounted for separately. */
|
||||
|
||||
amount += mPlaybackRate->SizeOfIncludingThis(aMallocSizeOf);
|
||||
amount += mDetune->SizeOfIncludingThis(aMallocSizeOf);
|
||||
|
Loading…
Reference in New Issue
Block a user