androidx / media

Jetpack Media3 support libraries for media use cases, including ExoPlayer, an extensible media player for Android
https://developer.android.com/media/media3
Apache License 2.0
1.57k stars 374 forks source link

How to mitigate OOMs when using a large MediaItem queue #1657

Open OxygenCobalt opened 3 weeks ago

OxygenCobalt commented 3 weeks ago

Some users of my app might load a queue of something like 20k+ songs, which naturally overloads the player (especially with gapless playback requiring a full MediaItem queue) and triggers excessive GCs and eventually an OOM error from the load.

I'm assuming this is largely unfixable since a lot of things will buckle under 20k+ songs, but what's the best way to mitigate this on my end?

Thanks

tonihei commented 3 weeks ago

Please see the summary in https://github.com/androidx/media/issues/81#issuecomment-1752643459 that lists a few of the open items and ideas. These are more focussed on the MediaSession communication though and your description sounds like it's solely about ExoPlayer?

I'd still recommend to only prepare the player with a more limited number of items if you can (a few hundred should work fine generally). Even though we try to postpone work until needed, there is some overhead even managing all the instances of internal classes like MediaSource or creating structures like a Timeline. Our plan to provide a form of "paging" player would help with that eventually. We can use this issue to track this feature request specifically.

Working with 20k+ items has the risk to run into bottlenecks elsewhere in your code as well of course, so it's worth investigating where you spend time and memory in your app even outside the player.

triggers excessive GCs and eventually an OOM error

I'm surprised this triggers OOM errors and is not just very slow. This implies there is indeed more going on other than allocating a few data classes. Are you using ExoPlayer.Builder.setUseLazyPreparation(false) by any chance? If you take a memory snapshot in Android Studio, you may be able to see what type of data types take up all the memory, and maybe that points to a useful lead.

OxygenCobalt commented 3 weeks ago

These are more focussed on the MediaSession communication though and your description sounds like it's solely about ExoPlayer?

Yep, I currently use Media3 session but avoided any binding in favor of my own internal communication layer, so functionally Media3 session only acts as a router for legacy media commands for my app.

I'd still recommend to only prepare the player with a more limited number of items if you can (a few hundred should work fine generally). Even though we try to postpone work until needed, there is some overhead even managing all the instances of internal classes like MediaSource or creating structures like a Timeline. Our plan to provide a form of "paging" player would help with that eventually. We can use this issue to track this feature request specifically.

I would definitely like to add paging on my end, but since I also leverage ShuffleOrder it ends up turning into an extremely hard problem and so I just hammer the player with the entire queue. A paging player provided by the library would be awesome.

Working with 20k+ items has the risk to run into bottlenecks elsewhere in your code as well of course, so it's worth investigating where you spend time and memory in your app even outside the player.

Yeah, this is an extreme case I don't really support first-class and haven't been able to optimize, but the issue itself only arose when I moved from a single-MediaItem player to loading queues of MediaItems instead.

I'm surprised this triggers OOM errors and is not just very slow. This implies there is indeed more going on other than allocating a few data classes. Are you using ExoPlayer.Builder.setUseLazyPreparation(false) by any chance? If you take a memory snapshot in Android Studio, you may be able to see what type of data types take up all the memory, and maybe that points to a useful lead.

No, not that I'm aware. I've tried to measure memory, but I can't make a large enough queue (I can only multiply 700 or so media items up to 20k, they have 20k distinct items) to reproduce the bug. I do notice an increase in memory as a whole, but I can't identify any particular object, and GCs clear it pretty quick.

@tonihei