androidx / media

Jetpack Media3 support libraries for media use cases, including ExoPlayer, an extensible media player for Android

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Observing OOM exceptions due to memory fragmentation

mayurk2 opened this issue · comments

We are using Exoplayer 2.16.1 in our application. We are observing that some users are facing crash due to OOM exception at our implementation of LoadControl.shouldContinueLoading().

On analysing the crashes we see that the issue is mostly due to memory fragmentation. This is from one of the crash report.

Fatal Exception: java.lang.OutOfMemoryError
Failed to allocate a 16 byte allocation with 770984 free bytes and 752KB until OOM, target footprint 402653184, growth limit 402653184; giving up on allocation because <1% of heap free after GC.

This issue is not specific to any particular device model / OS version.

We want to know if Exoplayer handles on memory fragmentation and low memory scenario and how it does?

We checked the DefaultLoadControl.shouldContinueLoading() and found that it handles the low memory case partially using targetBufferBytes. But the targetBufferBytes is updated at the initialisation time and hence looks like it does not handle run time memory crunch case. Also, it does not seem to handle memory fragmentation issue.

mostly due to memory fragmentation

I'm not quite sure how you derived that this is caused by fragmentation specifically vs simply running out of memory? I assume this problem is caused by generic memory pressure.

Besides that, ExoPlayer allocates its main sample queue memory in contiguous chunks of 64K bytes (when using DefaultLoadControl) to avoid unnecessary fragmentation.

But the targetBufferBytes is updated at the initialisation time and hence looks like it does not handle run time memory crunch case

You are right that DefaultLoadControl already has a memory limit. To make sure it's definitely applied, could you confirm that prioritizeTimeOverSizeThresholds is set to false (that's the default value). If not, the player may exceed the declared memory limit to achieve its minBufferMs value.

As you pointed out, there is no dynamic memory check to react to high memory pressure. The overall allocated memory is relatively small by default (~130MB) even for low-end devices, so we never saw the need to add dynamic adjustment. In most cases where we've seen OOM errors, they were caused by other code within the same app (or even other apps) and they were just surfaced inside the player at the moment of attempting the next allocation.