Closed Bug 1241096 Opened 5 years ago Closed 5 years ago

Large blocks of memory consumed by Web Audio node graph are not listed under webaudio in about:memory (but detected with DMD in heap-unclassified)

Categories

(Core :: Web Audio, defect, P2)

43 Branch
defect

Tracking

()

RESOLVED FIXED
mozilla48
Tracking Status
firefox48 --- fixed

People

(Reporter: jujjyl, Assigned: padenot)

References

(Blocks 1 open bug)

Details

(Whiteboard: [MemShrink:P2])

Attachments

(1 file)

We are trying to squeeze an Emscripten compiled asm.js application to a lower memory footprint mobile phones, and profiling the application with DMD, there is a suspiciously large amount of memory (70MB) going untracked that DMD is able to dig up. The call stack looks like this:

Unreported {
  80 blocks in heap block record 1 of 947
  73,826,304 bytes (73,661,000 requested / 165,304 slop)
  Individual block sizes: 16,863,232 x 2; 6,385,664 x 2; 1,069,056 x 2; 921,600 x 2; 831,488 x 2; 815,104 x 2; 634,880 x 2; 593,920 x 4; 561,152 x 2; 520,192 x 2; 487,424 x 2; 483,328 x 2; 446,464 x 2; 393,216 x 2; 380,928 x 2; 376,832 x 2; 368,640 x 2; 360,448 x 2; 348,160 x 4; 344,064 x 2; 335,872 x 2; 327,680 x 2; 311,296 x 2; 278,528 x 2; 237,568 x 2; 212,992 x 2; 147,456 x 4; 118,784 x 2; 114,688 x 4; 81,920 x 2; 77,824 x 4; 65,536 x 2; 57,344 x 2; 53,248 x 2; 24,576 x 2
  25.59% of the heap (25.59% cumulative)
  63.44% of unreported (63.44% cumulative)
  Allocated at {
    #01: malloc_impl (d:\gecko-dev\memory\build\replace_malloc.c:153)
    #02: js_malloc (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\js\utility.h:222)
    #03: js_pod_malloc<float> (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\js\utility.h:408)
    #04: mozilla::ThreadSharedFloatArrayBufferList::Create (d:\gecko-dev\dom\media\webaudio\audionodeengine.cpp:24)
    #05: mozilla::MediaDecodeTask::FinishDecode (d:\gecko-dev\dom\media\webaudio\mediabufferdecoder.cpp:370)
    #06: mozilla::MediaDecodeTask::SampleNotDecoded (d:\gecko-dev\dom\media\webaudio\mediabufferdecoder.cpp:332)
    #07: mozilla::MozPromise<enum mozilla::TrackInfo::TrackType,enum mozilla::MediaDataDecoder::DecoderFailureReason,1>::InvokeCallbackMethod<mozilla::H264Converter,void (__cdecl mozilla::H264Converter::*)(enum mozilla::TrackInfo::TrackType) __ptr64,enum mozilla:: (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\mozilla\mozpromise.h:436)
    #08: mozilla::MozPromise<RefPtr<mozilla::MediaData>,enum mozilla::MediaDecoderReader::NotDecodedReason,1>::MethodThenValue<mozilla::MediaDecodeTask,void (__cdecl mozilla::MediaDecodeTask::*)(mozilla::MediaData * __ptr64) __ptr64,void (__cdecl mozilla::MediaDec (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\mozilla\mozpromise.h:487)
    #09: mozilla::MozPromise<RefPtr<mozilla::MediaData>,enum mozilla::MediaDecoderReader::NotDecodedReason,1>::ThenValueBase::DoResolveOrReject (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\mozilla\mozpromise.h:385)
    #10: mozilla::MozPromise<RefPtr<mozilla::MediaData>,enum mozilla::MediaDecoderReader::NotDecodedReason,1>::ThenValueBase::ResolveOrRejectRunnable::Run (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\mozilla\mozpromise.h:319)
    #11: mozilla::AutoTaskDispatcher::TaskGroupRunnable::Run (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\mozilla\taskdispatcher.h:183)
    #12: mozilla::TaskQueue::Runner::Run (d:\gecko-dev\xpcom\threads\taskqueue.cpp:171)
    #13: nsThreadPool::Run (d:\gecko-dev\xpcom\threads\nsthreadpool.cpp:223)
    #14: nsThread::ProcessNextEvent (d:\gecko-dev\xpcom\threads\nsthread.cpp:989)
    #15: NS_ProcessNextEvent (d:\gecko-dev\xpcom\glue\nsthreadutils.cpp:297)
    #16: mozilla::ipc::MessagePumpForNonMainThreads::Run (d:\gecko-dev\ipc\glue\messagepump.cpp:326)
    #17: MessageLoop::RunInternal (d:\gecko-dev\ipc\chromium\src\base\message_loop.cc:235)
    #18: MessageLoop::RunHandler (d:\gecko-dev\ipc\chromium\src\base\message_loop.cc:228)
    #19: MessageLoop::Run (d:\gecko-dev\ipc\chromium\src\base\message_loop.cc:202)
    #20: nsThread::ThreadFunc (d:\gecko-dev\xpcom\threads\nsthread.cpp:403)
    #21: _PR_NativeRunThread (d:\gecko-dev\nsprpub\pr\src\threads\combined\pruthr.c:419)
    #22: pr_root (d:\gecko-dev\nsprpub\pr\src\md\windows\w95thred.c:91)
    #23: crt_at_quick_exit[ucrtbase +0x6be1d]
    #24: BaseThreadInitThunk[KERNEL32 +0x18102]
  }
}

This memory accounts for a large portion of all the memory used by the application. What are these blocks exactly? Can they be outright memory leaks? If not, they definitely look like application webaudio graph usage related, so it would be good to have them listed under webaudio node in about:memory for the content process. Looking at about:memory for the page, it only shows this for webaudio:

├────8.28 MB (01.53%) -- webaudio
│    ├──8.28 MB (01.53%) -- audio-node
│    │  ├──8.27 MB (01.53%) -- PannerNode
│    │  │  ├──8.16 MB (01.51%) ── hrtf-databases
│    │  │  └──0.12 MB (00.02%) ++ (3 tiny)
│    │  └──0.01 MB (00.00%) ++ (3 tiny)
│    └──0.00 MB (00.00%) ── audiocontext

so it is not accounting for the above blocks, and there is

├──111.76 MB (20.65%) ── heap-unclassified

which contains the 70MB according to the DMD tool.

How could one profile what is causing this large memory allocations in webaudio, so that we would be able to optimize the page memory usage to be smaller?
(In reply to Jukka Jylänki from comment #0)
> We are trying to squeeze an Emscripten compiled asm.js application to a
> lower memory footprint mobile phones, and profiling the application with
> DMD, there is a suspiciously large amount of memory (70MB) going untracked
> that DMD is able to dig up. The call stack looks like this:
> 
> Unreported {
>   80 blocks in heap block record 1 of 947
>   73,826,304 bytes (73,661,000 requested / 165,304 slop)
>   Individual block sizes: 16,863,232 x 2; 6,385,664 x 2; 1,069,056 x 2;
> 921,600 x 2; 831,488 x 2; 815,104 x 2; 634,880 x 2; 593,920 x 4; 561,152 x
> 2; 520,192 x 2; 487,424 x 2; 483,328 x 2; 446,464 x 2; 393,216 x 2; 380,928
> x 2; 376,832 x 2; 368,640 x 2; 360,448 x 2; 348,160 x 4; 344,064 x 2;
> 335,872 x 2; 327,680 x 2; 311,296 x 2; 278,528 x 2; 237,568 x 2; 212,992 x
> 2; 147,456 x 4; 118,784 x 2; 114,688 x 4; 81,920 x 2; 77,824 x 4; 65,536 x
> 2; 57,344 x 2; 53,248 x 2; 24,576 x 2
>   25.59% of the heap (25.59% cumulative)
>   63.44% of unreported (63.44% cumulative)
>   Allocated at {
>     #01: malloc_impl (d:\gecko-dev\memory\build\replace_malloc.c:153)
>     #02: js_malloc
> (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\js\utility.h:222)
>     #03: js_pod_malloc<float>
> (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\js\utility.h:408)
>     #04: mozilla::ThreadSharedFloatArrayBufferList::Create
> (d:\gecko-dev\dom\media\webaudio\audionodeengine.cpp:24)
>     #05: mozilla::MediaDecodeTask::FinishDecode
> (d:\gecko-dev\dom\media\webaudio\mediabufferdecoder.cpp:370)
>     #06: mozilla::MediaDecodeTask::SampleNotDecoded
> (d:\gecko-dev\dom\media\webaudio\mediabufferdecoder.cpp:332)
>     #07: mozilla::MozPromise<enum mozilla::TrackInfo::TrackType,enum
> mozilla::MediaDataDecoder::DecoderFailureReason,1>::
> InvokeCallbackMethod<mozilla::H264Converter,void (__cdecl
> mozilla::H264Converter::*)(enum mozilla::TrackInfo::TrackType) __ptr64,enum
> mozilla::
> (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\mozilla\mozpromise.h:436)
>     #08: mozilla::MozPromise<RefPtr<mozilla::MediaData>,enum
> mozilla::MediaDecoderReader::NotDecodedReason,1>::MethodThenValue<mozilla::
> MediaDecodeTask,void (__cdecl
> mozilla::MediaDecodeTask::*)(mozilla::MediaData * __ptr64) __ptr64,void
> (__cdecl mozilla::MediaDec
> (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\mozilla\mozpromise.h:487)
>     #09: mozilla::MozPromise<RefPtr<mozilla::MediaData>,enum
> mozilla::MediaDecoderReader::NotDecodedReason,1>::ThenValueBase::
> DoResolveOrReject
> (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\mozilla\mozpromise.h:385)
>     #10: mozilla::MozPromise<RefPtr<mozilla::MediaData>,enum
> mozilla::MediaDecoderReader::NotDecodedReason,1>::ThenValueBase::
> ResolveOrRejectRunnable::Run
> (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\mozilla\mozpromise.h:319)
>     #11: mozilla::AutoTaskDispatcher::TaskGroupRunnable::Run
> (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\mozilla\taskdispatcher.h:
> 183)
>     #12: mozilla::TaskQueue::Runner::Run
> (d:\gecko-dev\xpcom\threads\taskqueue.cpp:171)
>     #13: nsThreadPool::Run (d:\gecko-dev\xpcom\threads\nsthreadpool.cpp:223)
>     #14: nsThread::ProcessNextEvent
> (d:\gecko-dev\xpcom\threads\nsthread.cpp:989)
>     #15: NS_ProcessNextEvent (d:\gecko-dev\xpcom\glue\nsthreadutils.cpp:297)
>     #16: mozilla::ipc::MessagePumpForNonMainThreads::Run
> (d:\gecko-dev\ipc\glue\messagepump.cpp:326)
>     #17: MessageLoop::RunInternal
> (d:\gecko-dev\ipc\chromium\src\base\message_loop.cc:235)
>     #18: MessageLoop::RunHandler
> (d:\gecko-dev\ipc\chromium\src\base\message_loop.cc:228)
>     #19: MessageLoop::Run
> (d:\gecko-dev\ipc\chromium\src\base\message_loop.cc:202)
>     #20: nsThread::ThreadFunc (d:\gecko-dev\xpcom\threads\nsthread.cpp:403)
>     #21: _PR_NativeRunThread
> (d:\gecko-dev\nsprpub\pr\src\threads\combined\pruthr.c:419)
>     #22: pr_root (d:\gecko-dev\nsprpub\pr\src\md\windows\w95thred.c:91)
>     #23: crt_at_quick_exit[ucrtbase +0x6be1d]
>     #24: BaseThreadInitThunk[KERNEL32 +0x18102]
>   }
> }
> 
> This memory accounts for a large portion of all the memory used by the
> application. What are these blocks exactly?

They are decoded audio assets, basically the result of `decodeAudioData` calls (what is sent to the user using the callback or promise), and should be of type "AudioBuffer". They should be accounted for:

https://dxr.mozilla.org/mozilla-central/source/dom/media/webaudio/AudioBuffer.cpp#293

but they are not. Is something strange happening with those ?

> Can they be outright memory
> leaks?

It looks like the logic there is correct: allocate when decoding in [0] and then `Move` [1] [2] the memory to the `AudioBuffer`, but it could use a second pair of eyes maybe.

[0]: https://dxr.mozilla.org/mozilla-central/source/dom/media/webaudio/MediaBufferDecoder.cpp#370
[1]: https://dxr.mozilla.org/mozilla-central/source/dom/media/webaudio/MediaBufferDecoder.cpp#481
[2]: https://dxr.mozilla.org/mozilla-central/source/dom/media/webaudio/AudioBuffer.cpp#88

> If not, they definitely look like application webaudio graph usage
> related, so it would be good to have them listed under webaudio node in
> about:memory for the content process. Looking at about:memory for the page,
> it only shows this for webaudio:
> 
> ├────8.28 MB (01.53%) -- webaudio
> │    ├──8.28 MB (01.53%) -- audio-node
> │    │  ├──8.27 MB (01.53%) -- PannerNode
> │    │  │  ├──8.16 MB (01.51%) ── hrtf-databases
> │    │  │  └──0.12 MB (00.02%) ++ (3 tiny)
> │    │  └──0.01 MB (00.00%) ++ (3 tiny)
> │    └──0.00 MB (00.00%) ── audiocontext
> 
> so it is not accounting for the above blocks, and there is
> 
> ├──111.76 MB (20.65%) ── heap-unclassified
> 
> which contains the 70MB according to the DMD tool.
> 
> How could one profile what is causing this large memory allocations in
> webaudio, so that we would be able to optimize the page memory usage to be
> smaller?

In the meantime, look at the size of the AudioBuffer resulting from `decodeAudioData`, I'd say, that would be the biggest memory cost.
Blocks: DarkMatter
Whiteboard: [MemShrink]
There should not be anything special with these audio blocks.

If this source of allocations should be accounted, it looks like there's some bug there. Here's another STR:

1. Visit http://beta.unity3d.com/jonas/DT2/
2. Open either level in the game 
3. Esc out from fullscreen, and keep the tab open, but open a new about:memory tab
4. Tap the Free memory: GC/CC/Minimize memory usage buttons
5. Take a Measure snapshot

The following is observed:

├────418.64 MB (31.79%) ── heap-unclassified
├─────36.94 MB (02.80%) -- webaudio
│     ├──36.93 MB (02.80%) -- audio-node
│     │  ├──20.45 MB (01.55%) -- AudioBufferSourceNode
│     │  │  ├──20.36 MB (01.55%) ── dom-nodes [145]
│     │  │  └───0.10 MB (00.01%) -- (2 tiny)
│     │  │      ├──0.07 MB (00.01%) ── stream-objects [145]
│     │  │      └──0.03 MB (00.00%) ── engine-objects [145]
│     │  ├──16.31 MB (01.24%) -- PannerNode
│     │  │  ├───8.16 MB (00.62%) ── hrtf-databases
│     │  │  ├───8.03 MB (00.61%) ── engine-objects [145]
│     │  │  ├───0.07 MB (00.01%) ── stream-objects [145]
│     │  │  └───0.06 MB (00.00%) ── dom-nodes [145]
│     │  └───0.16 MB (00.01%) -- (2 tiny)
│     │      ├──0.13 MB (00.01%) -- GainNode
│     │      │  ├──0.07 MB (00.01%) ── stream-objects [145]
│     │      │  ├──0.05 MB (00.00%) ── dom-nodes [145]
│     │      │  └──0.01 MB (00.00%) ── engine-objects [145]
│     │      └──0.03 MB (00.00%) -- AudioDestinationNode
│     │         ├──0.02 MB (00.00%) ── stream-objects
│     │         ├──0.01 MB (00.00%) ── dom-nodes
│     │         └──0.00 MB (00.00%) ── engine-objects
│     └───0.01 MB (00.00%) ── audiocontext

Which suggests that the audio data is not ending up as part of webaudio tree. Performing the run with DMD enabled (https://developer.mozilla.org/en-US/docs/Mozilla/Performance/DMD) finds a look inside the heap-unclassified as

Unreported {
  230 blocks in heap block record 1 of 3,344
  118,894,592 bytes (118,445,608 requested / 448,984 slop)
  Individual block sizes: 11,636,736 x 2; 9,211,904 x 2; 1,921,024; 1,650,688; 1,617,920; 1,564,672; 1,544,192; 1,490,944; 1,400,832; 1,228,800 x 2; 1,200,128 x 2; 1,191,936; 1,130,496; 1,097,728; 1,089,536; 942,080; 929,792; 913,408; 864,256; 761,856; 737,280; 716,800; 700,416; 688,128; 684,032 x 2; 679,936; 675,840 x 2; 655,360; 647,168; 643,072; 630,784; 598,016; 585,728; 581,632; 569,344; 557,056; 544,768; 503,808 x 2; 499,712 x 2; 495,616 x 2; 475,136; 462,848; 454,656; 446,464 x 4; 425,984; 421,888; 417,792; 413,696; 409,600; 401,408; 393,216; 380,928 x 2; 376,832; 368,640; 348,160 x 5; 344,064 x 2; 339,968; 331,776 x 4; 327,680 x 3; 319,488; 315,392 x 3; 307,200 x 4; 299,008 x 3; 294,912 x 2; 290,816; 286,720; 282,624; 274,432; 270,336 x 3; 262,144 x 2; 258,048 x 3; 249,856 x 3; 245,760 x 4; 241,664 x 2; 237,568 x 2; 233,472; 229,376; 225,280; 221,184; 212,992; 208,896 x 3; 204,800 x 3; 200,704 x 3; 196,608 x 3; 192,512 x 2; 188,416 x 4; 184,320; 180,224 x 3; 176,128 x 2; 172,032; 167,936 x 2; 163,840 x 2; 159,744 x 6; 155,648; 151,552 x 2; 147,456 x 3; 143,360 x 3; 139,264 x 4; 135,168; 131,072 x 4; 126,976 x 4; 122,880 x 2; 118,784 x 3; 114,688 x 2; 110,592 x 2; 106,496; 102,400 x 5; 98,304 x 2; 94,208 x 2; 90,112; 86,016; 81,920 x 3; 77,824 x 2; 73,728 x 2; 69,632 x 3; 61,440 x 2; 57,344; 53,248 x 6; 49,152 x 4; 36,864; 32,768; 8,192 x 4
  16.89% of the heap (16.89% cumulative)
  25.85% of unreported (25.85% cumulative)
  Allocated at {
    #01: malloc_impl (d:\gecko-dev\memory\build\replace_malloc.c:153)
    #02: js_malloc (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\js\utility.h:222)
    #03: js_pod_malloc<float> (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\js\utility.h:408)
    #04: mozilla::ThreadSharedFloatArrayBufferList::Create (d:\gecko-dev\dom\media\webaudio\audionodeengine.cpp:24)
    #05: mozilla::MediaDecodeTask::FinishDecode (d:\gecko-dev\dom\media\webaudio\mediabufferdecoder.cpp:370)
    #06: mozilla::MediaDecodeTask::SampleNotDecoded (d:\gecko-dev\dom\media\webaudio\mediabufferdecoder.cpp:332)
    #07: mozilla::MozPromise<enum mozilla::TrackInfo::TrackType,enum mozilla::MediaDataDecoder::DecoderFailureReason,1>::InvokeCallbackMethod<mozilla::H264Converter,void (__cdecl mozilla::H264Converter::*)(enum mozilla::TrackInfo::TrackType) __ptr64,enum mozilla:: (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\mozilla\mozpromise.h:436)
    #08: mozilla::MozPromise<RefPtr<mozilla::MediaData>,enum mozilla::MediaDecoderReader::NotDecodedReason,1>::MethodThenValue<mozilla::MediaDecodeTask,void (__cdecl mozilla::MediaDecodeTask::*)(mozilla::MediaData * __ptr64) __ptr64,void (__cdecl mozilla::MediaDec (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\mozilla\mozpromise.h:487)
    #09: mozilla::MozPromise<RefPtr<mozilla::MediaData>,enum mozilla::MediaDecoderReader::NotDecodedReason,1>::ThenValueBase::DoResolveOrReject (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\mozilla\mozpromise.h:385)
    #10: mozilla::MozPromise<RefPtr<mozilla::MediaData>,enum mozilla::MediaDecoderReader::NotDecodedReason,1>::ThenValueBase::ResolveOrRejectRunnable::Run (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\mozilla\mozpromise.h:319)
    #11: mozilla::AutoTaskDispatcher::TaskGroupRunnable::Run (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\mozilla\taskdispatcher.h:183)
    #12: mozilla::TaskQueue::Runner::Run (d:\gecko-dev\xpcom\threads\taskqueue.cpp:171)
    #13: nsThreadPool::Run (d:\gecko-dev\xpcom\threads\nsthreadpool.cpp:223)
    #14: nsThread::ProcessNextEvent (d:\gecko-dev\xpcom\threads\nsthread.cpp:989)
    #15: NS_ProcessNextEvent (d:\gecko-dev\xpcom\glue\nsthreadutils.cpp:297)
    #16: mozilla::ipc::MessagePumpForNonMainThreads::Run (d:\gecko-dev\ipc\glue\messagepump.cpp:326)
    #17: MessageLoop::RunInternal (d:\gecko-dev\ipc\chromium\src\base\message_loop.cc:235)
    #18: MessageLoop::RunHandler (d:\gecko-dev\ipc\chromium\src\base\message_loop.cc:228)
    #19: MessageLoop::Run (d:\gecko-dev\ipc\chromium\src\base\message_loop.cc:202)
    #20: nsThread::ThreadFunc (d:\gecko-dev\xpcom\threads\nsthread.cpp:403)
    #21: _PR_NativeRunThread (d:\gecko-dev\nsprpub\pr\src\threads\combined\pruthr.c:419)
    #22: pr_root (d:\gecko-dev\nsprpub\pr\src\md\windows\w95thred.c:91)
    #23: crt_at_quick_exit[ucrtbase +0x6be1d]
    #24: BaseThreadInitThunk[KERNEL32 +0x18102]
  }
}

Unreported {
  22 blocks in heap block record 2 of 3,344
  7,614,464 bytes (7,573,328 requested / 41,136 slop)
  Individual block sizes: 962,560; 811,008; 716,800; 704,512; 585,728; 446,464 x 3; 352,256; 307,200; 286,720; 278,528; 229,376; 212,992; 180,224; 176,128; 163,840; 131,072; 65,536; 57,344; 45,056; 8,192
  1.08% of the heap (17.97% cumulative)
  1.66% of unreported (27.51% cumulative)
  Allocated at {
    #01: malloc_impl (d:\gecko-dev\memory\build\replace_malloc.c:153)
    #02: js_malloc (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\js\utility.h:222)
    #03: js_pod_malloc<float> (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\js\utility.h:408)
    #04: mozilla::ThreadSharedFloatArrayBufferList::Create (d:\gecko-dev\dom\media\webaudio\audionodeengine.cpp:24)
    #05: mozilla::MediaDecodeTask::FinishDecode (d:\gecko-dev\dom\media\webaudio\mediabufferdecoder.cpp:370)
    #06: mozilla::MediaDecodeTask::SampleNotDecoded (d:\gecko-dev\dom\media\webaudio\mediabufferdecoder.cpp:332)
    #07: mozilla::MozPromise<enum mozilla::TrackInfo::TrackType,enum mozilla::MediaDataDecoder::DecoderFailureReason,1>::InvokeCallbackMethod<mozilla::H264Converter,void (__cdecl mozilla::H264Converter::*)(enum mozilla::TrackInfo::TrackType) __ptr64,enum mozilla:: (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\mozilla\mozpromise.h:436)
    #08: mozilla::MozPromise<RefPtr<mozilla::MediaData>,enum mozilla::MediaDecoderReader::NotDecodedReason,1>::MethodThenValue<mozilla::MediaDecodeTask,void (__cdecl mozilla::MediaDecodeTask::*)(mozilla::MediaData * __ptr64) __ptr64,void (__cdecl mozilla::MediaDec (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\mozilla\mozpromise.h:487)
    #09: mozilla::MozPromise<RefPtr<mozilla::MediaData>,enum mozilla::MediaDecoderReader::NotDecodedReason,1>::ThenValueBase::DoResolveOrReject (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\mozilla\mozpromise.h:385)
    #10: mozilla::MozPromise<RefPtr<mozilla::MediaData>,enum mozilla::MediaDecoderReader::NotDecodedReason,1>::ThenValueBase::ResolveOrRejectRunnable::Run (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\mozilla\mozpromise.h:319)
    #11: mozilla::AutoTaskDispatcher::TaskGroupRunnable::Run (d:\gecko-dev\obj-x86_64-pc-mingw32\dist\include\mozilla\taskdispatcher.h:183)
    #12: mozilla::TaskQueue::Runner::Run (d:\gecko-dev\xpcom\threads\taskqueue.cpp:171)
    #13: nsThreadPool::Run (d:\gecko-dev\xpcom\threads\nsthreadpool.cpp:223)
    #14: nsThread::ProcessNextEvent (d:\gecko-dev\xpcom\threads\nsthread.cpp:989)
    #15: NS_ProcessNextEvent (d:\gecko-dev\xpcom\glue\nsthreadutils.cpp:297)
    #16: mozilla::ipc::MessagePumpForNonMainThreads::Run (d:\gecko-dev\ipc\glue\messagepump.cpp:356)
    #17: MessageLoop::RunInternal (d:\gecko-dev\ipc\chromium\src\base\message_loop.cc:235)
    #18: MessageLoop::RunHandler (d:\gecko-dev\ipc\chromium\src\base\message_loop.cc:228)
    #19: MessageLoop::Run (d:\gecko-dev\ipc\chromium\src\base\message_loop.cc:202)
    #20: nsThread::ThreadFunc (d:\gecko-dev\xpcom\threads\nsthread.cpp:403)
    #21: _PR_NativeRunThread (d:\gecko-dev\nsprpub\pr\src\threads\combined\pruthr.c:419)
    #22: pr_root (d:\gecko-dev\nsprpub\pr\src\md\windows\w95thred.c:91)
    #23: crt_at_quick_exit[ucrtbase +0x6be1d]
    #24: BaseThreadInitThunk[KERNEL32 +0x18102]
  }
}

It would be good to get these under webaudio in about:memory. Can you try to reproduce Paul?
Flags: needinfo?(padenot)
We can get those into about:memory under Web Audio for sure. I don't think I'm the most qualified to do this, maybe erahm can have a look ? He's done things like that in the past.
Flags: needinfo?(padenot) → needinfo?(erahm)
It's possible this is a leak, lets split off a bug for the reporting part.
Whiteboard: [MemShrink] → [MemShrink:P2]
Jukka, is the memory freed when leaving the page?
Flags: needinfo?(jujjyl)
Paul: Per erahm's comment 4 - how likely is this a leak, as opposed to just a reporting issue?
Flags: needinfo?(padenot)
The memory is freed when leaving the page, so it is likely that this is only a reporting issue.
Flags: needinfo?(jujjyl)
(In reply to Paul Adenot (:padenot) from comment #3)
> We can get those into about:memory under Web Audio for sure. I don't think
> I'm the most qualified to do this, maybe erahm can have a look ? He's done
> things like that in the past.

It's probably best that someone actively working on web audio track down the reporting issue.
Flags: needinfo?(erahm)
Rank: 25
Priority: -- → P2
We are helping a Unity3D game developer work on optimizing memory usage on their title, and they are reporting 300MB of used memory in heap-unclassified. Our suspect is that it corresponds to memory used by Web Audio. The game is at 

https://apps.facebook.com/topeleven/

where the memory report shows

1,158.56 MB (100.0%) -- explicit
├────577.61 MB (49.86%) -- window-objects
│    ├──562.18 MB (48.52%) -- top(https://apps.facebook.com/topeleven/, id=8)
│    │  ├──545.36 MB (47.07%) -- active
│    │  │  ├──522.87 MB (45.13%) -- window(https://app.topeleven.com/fb/current/www/)
│    │  │  │  ├──521.78 MB (45.04%) -- js-compartment(https://app.topeleven.com/fb/current/www/)
│    │  │  │  │  ├──520.11 MB (44.89%) -- classes
│    │  │  │  │  │  ├──431.83 MB (37.27%) -- class(ArrayBuffer)
│    │  │  │  │  │  │  ├──431.83 MB (37.27%) -- objects
│    │  │  │  │  │  │  │  ├──384.00 MB (33.14%) ── non-heap/elements/asm.js
│    │  │  │  │  │  │  │  ├───47.83 MB (04.13%) ── malloc-heap/elements/normal
│    │  │  │  │  │  │  │  └────0.01 MB (00.00%) ── gc-heap
│    │  │  │  │  │  │  └────0.00 MB (00.00%) ++ shapes/gc-heap
│    │  │  │  │  │  ├───84.35 MB (07.28%) -- class(WasmModuleObject)
│    │  │  │  │  │  │   ├──84.35 MB (07.28%) -- objects
│    │  │  │  │  │  │   │  ├──44.02 MB (03.80%) ── non-heap/code/asm.js
│    │  │  │  │  │  │   │  ├──40.33 MB (03.48%) ── malloc-heap/misc
│    │  │  │  │  │  │   │  └───0.00 MB (00.00%) ── gc-heap
│    │  │  │  │  │  │   └───0.00 MB (00.00%) ++ shapes/gc-heap
│    │  │  │  │  │  └────3.93 MB (00.34%) ++ (14 tiny)
│    │  │  │  │  └────1.67 MB (00.14%) ++ (7 tiny)
│    │  │  │  └────1.09 MB (00.09%) ++ (4 tiny)
│    │  │  ├───20.85 MB (01.80%) ++ window(https://apps.facebook.com/topeleven/)
│    │  │  └────1.64 MB (00.14%) ++ (4 tiny)
│    │  └───16.82 MB (01.45%) ++ js-zone(0x29809c0e800)
│    └───15.43 MB (01.33%) ++ (6 tiny)
├────306.65 MB (26.47%) ── heap-unclassified
├────153.56 MB (13.25%) -- js-non-window
│    ├───99.56 MB (08.59%) -- runtime
│    │   ├──82.00 MB (07.08%) -- script-sources
│    │   │  ├──79.88 MB (06.89%) -- source(scripts=1, blob:https://app.topeleven.com/db1cd1b4-71cb-4877-a394-20e4a1263d3d)
│    │   │  │  ├──79.88 MB (06.89%) ── uncompressed
│    │   │  │  └───0.00 MB (00.00%) ── misc
│    │   │  └───2.13 MB (00.18%) ++ (45 tiny)
│    │   └──17.56 MB (01.52%) ++ (11 tiny)
│    ├───50.99 MB (04.40%) -- zones
│    │   ├──45.49 MB (03.93%) ++ zone(0x29872173800)
│    │   └───5.51 MB (00.48%) ++ (6 tiny)
│    └────3.01 MB (00.26%) ++ gc-heap
├─────64.06 MB (05.53%) -- dom
│     ├──64.02 MB (05.53%) -- memory-file-data/large
│     │  ├──64.00 MB (05.52%) ── file(length=41875814, sha1=882bf68d6735bc8c8f680060db38464bb014e088)
│     │  └───0.02 MB (00.00%) ── file(length=5430, sha1=49263695f6b0cdd72f45cf1b775e660fdc36c606) [2]
│     └───0.05 MB (00.00%) ── event-listener-managers-hash
├─────37.69 MB (03.25%) ++ (23 tiny)
└─────19.00 MB (01.64%) -- heap-overhead
      ├──14.79 MB (01.28%) ── bin-unused
      └───4.21 MB (00.36%) ++ (2 tiny)

Would it be possible to bump up the priority for this bug? It would help the developer do profiles of whether the 300MB really is audio, and give clues what to do about it.
I'm taking this, investigation shows that there might be a leak somewhere.
Assignee: nobody → padenot
Flags: needinfo?(padenot)
Great, thanks Paul for the quick response!

If you find a need to obtain an offline test case, let me know, and I can try digging some stuff up. The facebook page should be live for testing this as well (as well as Jonas's Dead Trigger 2 demo page).
Thanks Jukka, I've written my own, using a simple xhr+decodeAudioData+a one hour silent mp3 file that decodes to around 600MB of AudioBuffer, so it's very visible in about:memory if we leak it.
After investigation, I found that there is no leak, but there are a number of issues around memory reporting of audio buffers:

- If an `AudioBuffer` is being used by an `AudioNode`, it's memory usage is being reported as being in this Node.
- If the `AudioBuffer` is being used by multiple `AudioNode`, it's counted multiple times, even though the data is shared, this is clearly wrong, and about:memory shows a warning.
- If the `AudioBuffer` is not being used (for example, it's being kept around in an object or array for later use), it goes in heap-unclassified.

What we need to do is to be able to visit the `AudioBuffer` themselves, so we're not double-counting things.
MozReview-Commit-ID: GHiauyyD3R2
Attachment #8736770 - Flags: review?(erahm)
Comment on attachment 8736770 [details] [diff] [review]
Add a better memory reporting system for AudioBuffers. r=

Review of attachment 8736770 [details] [diff] [review]:
-----------------------------------------------------------------

This looks good to me, just one minor comment. r=me either way.

::: dom/media/webaudio/AudioBuffer.h
@@ +32,5 @@
> + * 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

This could (or maybe should) just be internal to AudioBuffer.cpp, right?
Attachment #8736770 - Flags: review?(erahm) → review+
Jukka, it should be real clear how much memory is used by AudioBuffers now, there is a new section in about:memory.
Flags: needinfo?(jujjyl)
sorry had to back this out for crashes like https://treeherder.mozilla.org/logviewer.html#?job_id=24944355&repo=mozilla-inbound
Flags: needinfo?(padenot)
https://hg.mozilla.org/mozilla-central/rev/55fa7abf9863
Status: NEW → RESOLVED
Closed: 5 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla48
clearing needinfo
Flags: needinfo?(padenot)
Great work, thanks! Testing on the Top Eleven page, I am seeing a good decomposition between audio and heap-unclassified now:

1,053.69 MB (100.0%) -- explicit
├────573.05 MB (54.39%) ++ window-objects
├────248.80 MB (23.61%) -- webaudio
│    ├──248.80 MB (23.61%) ── audiobuffer
│    └────0.00 MB (00.00%) ++ (2 tiny)
├────112.87 MB (10.71%) ++ js-non-window
├─────64.01 MB (06.08%) ++ dom
├─────38.67 MB (03.67%) ── heap-unclassified
└─────16.29 MB (01.55%) ++ (17 tiny)

The developer is aware of the large amount of audio memory being consumed by the page and they are looking for ways to stream in better on demand. (btw, if we had that 16-bit int format support, that would be 124MB less memory consumed by this page for free, since Unity3D games encode 99% of their audio in 16-bit formats, and it's very rare to need 32-bit floats)

Thanks again!
Flags: needinfo?(jujjyl)
You need to log in before you can comment on or make changes to this bug.