Closed Bug 976273 Opened 10 years ago Closed 10 years ago

<video> should register a "memory-pressure" observer, and do something on low memory

Categories

(Core :: Audio/Video, defect)

defect
Not set
normal

Tracking

()

RESOLVED WONTFIX

People

(Reporter: cpearce, Assigned: cpearce)

References

Details

(Whiteboard: [MemShrink:P2])

Attachments

(1 file)

We should register a "memory-pressure" observer, and do something sensible when it occurs.

See nsIMemory.idl

Ideas:
* Be more aggressive in shutting down idle decoders.
* Purge cached decoded A/V data, perhaps only for non-playing media.
* Reduce the number of threads in our thread pools.
* Reduce the size of our decode-ahead caching of decoded samples.
* Write partial blocks in the media cache to disk?
Whiteboard: [MemShrink]
Whiteboard: [MemShrink] → [MemShrink:P2]
I'll work on this in order to help fix bug 982695.
Assignee: nobody → cpearce
Attached patch WIP PatchSplinter Review
I added a memory pressure observer to HTMLMediaElement that simply shuts down the decoders when the observer receives memory pressure notification, and when I stress tested Win32 builds (on this page: http://people.mozilla.org/~cpearce/stress/) firefox no longer crashes (which is good) but the window ends up completely black after the memory pressure observer has finished running. Even the browser chrome is black and unusable. This is bad.

njn: Is there a way to make memory-pressure observer topic fire earlier?

I think we'll need a different strategy to solve this. I think we really need to keep a limit on the number of decoders that we create, as we have no control over how much resources the platform's decoders use up.

So maybe we should do something like limiting the number of <video> and <audio> elements that we can have with active decoders to some upper limit. So say for video we limit active video decoders to $SystemMemoryInMB / 32, and for audio $SystemMemoryInMB / 4, or somesuch. We'd need to cap $SystemMemoryInMB to 2GB in 32bit Firefox. When we reach the limit, we can delay the HTMLMediaElement load algorithm while we wait for a decoder slot to free up.
Attachment #8398178 - Flags: feedback?(n.nethercote)
> njn: Is there a way to make memory-pressure observer topic fire earlier?

Not that I know of, sorry. I'm not even sure what causes it to fire on desktop.
FYI, we fire memory-pressure on Win32 Firefox with the following stack:

xul.dll!NS_DispatchEventualMemoryPressure(MemoryPressureState state=MemPressure_New) Line 34	C++
xul.dll!`anonymous namespace'::CheckMemAvailable() Line 216	C++
xul.dll!`anonymous namespace'::VirtualAllocHook(void * aAddress=0x3dc80000, unsigned long aSize=65536, unsigned long aAllocationType=12288, unsigned long aProtect=64) Line 261	C++
mozjs.dll!JSC::ExecutableAllocator::systemAlloc(unsigned int n=65536) Line 101	C++
mozjs.dll!JSC::ExecutableAllocator::createPool(unsigned int n=65536) Line 328	C++
mozjs.dll!JSC::ExecutableAllocator::poolForSize(unsigned int n=864) Line 366	C++
mozjs.dll!JSC::ExecutableAllocator::alloc(unsigned int n=864, JSC::ExecutablePool * * poolp=0x92b2d02c, JSC::CodeKind type=BASELINE_CODE) Line 254	C++
mozjs.dll!js::jit::Linker::newCode<1>(JSContext * cx=0x0c8a6fbc, JSC::ExecutableAllocator * execAlloc=0x0c8d4830, JSC::CodeKind kind=BASELINE_CODE) Line 51	C++
mozjs.dll!js::jit::BaselineCompiler::compile() Line 111	C++
mozjs.dll!js::jit::BaselineCompile(JSContext * cx=0x110ed580, JS::Handle<JSScript *> script={...}) Line 236	C++
mozjs.dll!CanEnterBaselineJIT(JSContext * cx=0x110ed580, JS::Handle<JSScript *> script={...}, bool osr=true) Line 300	C++
mozjs.dll!js::jit::CanEnterBaselineAtBranch(JSContext * cx=0x110ed580, js::InterpreterFrame * fp=0x1a21bef8, bool newType=false) Line 319	C++
mozjs.dll!Interpret(JSContext * cx, js::RunState & state) Line 1710	C++
mozjs.dll!js::RunScript(JSContext * cx=0x110ed580, js::RunState & state={...}) Line 423	C++
mozjs.dll!js::Invoke(JSContext * cx=0x110ed580, JS::CallArgs args={...}, js::MaybeConstruct construct=NO_CONSTRUCT) Line 498	C++
mozjs.dll!js_fun_apply(JSContext * cx=0x110ed580, unsigned int argc=2, JS::Value * vp=0x1a21bd28) Line 1010	C++
mozjs.dll!js::Invoke(JSContext * cx=0x110ed580, JS::CallArgs args={...}, js::MaybeConstruct construct=NO_CONSTRUCT) Line 469	C++
mozjs.dll!Interpret(JSContext * cx, js::RunState & state) Line 2614	C++
mozjs.dll!js::RunScript(JSContext * cx=0x110ed580, js::RunState & state={...}) Line 423	C++
mozjs.dll!js::Invoke(JSContext * cx=0x110ed580, JS::CallArgs args={...}, js::MaybeConstruct construct=NO_CONSTRUCT) Line 498	C++
mozjs.dll!js::Invoke(JSContext * cx=0x110ed580, const JS::Value & thisv={...}, const JS::Value & fval={...}, unsigned int argc=1, const JS::Value * argv=0x92b2ef40, JS::MutableHandle<JS::Value> rval={...}) Line 532	C++
mozjs.dll!JS::Call(JSContext * cx=0x110ed580, JS::Handle<JS::Value> thisv={...}, JS::Handle<JS::Value> fval={...}, const JS::HandleValueArray & args={...}, JS::MutableHandle<JS::Value> rval={...}) Line 4907	C++
xul.dll!mozilla::dom::EventHandlerNonNull::Call(JSContext * cx=0x110ed580, JS::Handle<JS::Value> aThisVal={...}, mozilla::dom::Event & event={...}, mozilla::ErrorResult & aRv={...}) Line 36	C++
xul.dll!mozilla::dom::EventHandlerNonNull::Call<nsISupports *>(nsISupports * const & thisObjPtr=0x16d2a320, mozilla::dom::Event & event={...}, mozilla::ErrorResult & aRv={...}, mozilla::dom::CallbackObject::ExceptionHandling aExceptionHandling=eReportExceptions) Line 62	C++
xul.dll!nsJSEventListener::HandleEvent(nsIDOMEvent * aEvent=0x0ca89fb8) Line 218	C++
xul.dll!mozilla::EventListenerManager::HandleEventSubType(mozilla::EventListenerManager::Listener * aListener=0x0c72e798, nsIDOMEvent * aDOMEvent=0x0ca89fb8, mozilla::dom::EventTarget * aCurrentTarget=0x16d2a320) Line 954	C++
xul.dll!mozilla::EventListenerManager::HandleEventInternal(nsPresContext * aPresContext=0x00000000, mozilla::WidgetEvent * aEvent=0x18d9c738, nsIDOMEvent * * aDOMEvent=0x92b2f36c, mozilla::dom::EventTarget * aCurrentTarget=0x16d2a320, nsEventStatus * aEventStatus=0x92b2f370) Line 1016	C++
xul.dll!mozilla::EventListenerManager::HandleEvent(nsPresContext * aPresContext=0x00000000, mozilla::WidgetEvent * aEvent=0x18d9c738, nsIDOMEvent * * aDOMEvent=0x92b2f36c, mozilla::dom::EventTarget * aCurrentTarget=0x16d2a320, nsEventStatus * aEventStatus=0x92b2f370) Line 328	C++
xul.dll!mozilla::EventTargetChainItem::HandleEvent(mozilla::EventChainPostVisitor & aVisitor={...}, mozilla::ELMCreationDetector & aCd={...}) Line 197	C++
xul.dll!mozilla::EventTargetChainItem::HandleEventTargetChain(nsTArray<mozilla::EventTargetChainItem> & aChain={...}, mozilla::EventChainPostVisitor & aVisitor={...}, mozilla::EventDispatchingCallback * aCallback=0x00000000, mozilla::ELMCreationDetector & aCd={...}) Line 289	C++
xul.dll!mozilla::EventDispatcher::Dispatch(nsISupports * aTarget=0x16d2a320, nsPresContext * aPresContext=0x00000000, mozilla::WidgetEvent * aEvent=0x18d9c738, nsIDOMEvent * aDOMEvent=0x0ca89fb8, nsEventStatus * aEventStatus=0x92b2f42c, mozilla::EventDispatchingCallback * aCallback=0x00000000, nsCOMArray<mozilla::dom::EventTarget> * aTargets=0x00000000) Line 600	C++
xul.dll!mozilla::EventDispatcher::DispatchDOMEvent(nsISupports * aTarget=0x16d2a320, mozilla::WidgetEvent * aEvent=0x00000000, nsIDOMEvent * aDOMEvent=0x01a89fb8, nsPresContext * aPresContext=0x00000000, nsEventStatus * aEventStatus=0x92b2f42c) Line 662	C++
xul.dll!nsINode::DispatchDOMEvent(mozilla::WidgetEvent * aEvent=0x00000000, nsIDOMEvent * aDOMEvent=0x0ca89fb8, nsPresContext * aPresContext=0x00000000, nsEventStatus * aEventStatus=0x92b2f42c) Line 1219	C++
xul.dll!`anonymous namespace'::MessageEventRunnable::DispatchDOMEvent(JSContext * aCx=0x110ed580, mozilla::dom::workers::WorkerPrivate * aWorkerPrivate=0x10eb7a38, nsDOMEventTargetHelper * aTarget=0x16d2a320, bool aIsMainThread=false) Line 1004	C++
xul.dll!`anonymous namespace'::MessageEventRunnable::WorkerRun(JSContext * aCx=0x110ed580, mozilla::dom::workers::WorkerPrivate * aWorkerPrivate=0x10eb7a38) Line 1052	C++
xul.dll!mozilla::dom::workers::WorkerRunnable::Run() Line 312	C++
xul.dll!nsThread::ProcessNextEvent(bool mayWait=false, bool * result=0x92b2f533) Line 694	C++
xul.dll!NS_ProcessNextEvent(nsIThread * thread=0x018dc6d0, bool mayWait=false) Line 263	C++
xul.dll!mozilla::dom::workers::WorkerPrivate::DoRunLoop(JSContext * aCx=0x110ed580) Line 4052	C++
xul.dll!`anonymous namespace'::WorkerThreadPrimaryRunnable::Run() Line 2561	C++
xul.dll!nsThread::ProcessNextEvent(bool mayWait=false, bool * result=0x92b2f6a7) Line 694	C++
xul.dll!NS_ProcessNextEvent(nsIThread * thread=0x018dc6d0, bool mayWait=false) Line 263	C++
xul.dll!mozilla::ipc::MessagePumpForNonMainThreads::Run(base::MessagePump::Delegate * aDelegate=0x11a7b430) Line 307	C++
xul.dll!MessageLoop::RunHandler() Line 220	C++
xul.dll!MessageLoop::Run() Line 194	C++
xul.dll!nsThread::ThreadFunc(void * arg=0x11a7b430) Line 317	C++
nss3.dll!_PR_NativeRunThread(void * arg=0x188cf9a0) Line 419	C
nss3.dll!pr_root(void * arg=0x19e4c370) Line 90	C
msvcr100.dll!_callthreadstartex() Line 314	C
msvcr100.dll!_threadstartex(void * ptd=0x1a6c5c78) Line 292	C
kernel32.dll!@BaseThreadInitThunk@12()	Unknown
ntdll.dll!__RtlUserThreadStart()	Unknown
ntdll.dll!__RtlUserThreadStart@8()	Unknown
We're not going to do this for now. We need to find a better solution.

Even if we destroy all decoders on a low memory situation, it's easy to overwhelm the allocator by creating more video elements. Without a memory-pressure observer, we crash when we create too many media elements. But with a memory-pressure observer, in an ongoing memory-pressure situation the browser purges too much and chrome and content fails to paint, making the browser unusable.

On B2G on low memory we kill the browser app, but that isn't bringing down the OS, so I think the situation is not urgent there for now.

I think we need to do something smarter, like limiting the number of decoders we allow to be alive at once, and having some sort of system to prioritize which media elements get decoders, and making decoders on idle media elements dormant.
Status: NEW → RESOLVED
Closed: 10 years ago
Resolution: --- → WONTFIX
Comment on attachment 8398178 [details] [diff] [review]
WIP Patch

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

Sorry, I missed the f? request here. But since the bug has been WONTFIX'd, I guess I don't need to do anything now.
Attachment #8398178 - Flags: feedback?(n.nethercote)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: