Multiple PulseAudio contexts cause Out of Memory #182

Closed
opened 2020-03-11 23:06:49 -05:00 by alesliehughes · 7 comments
alesliehughes commented 2020-03-11 23:06:49 -05:00 (Migrated from github.com)

Game Gauntlet.

When running with xaudio, the game runs out memory when trying to load character selection.

Basically the game creates a bunch of IXAudio2 CreateMasteringVoice objects, about 10.
For each CreateMasteringVoice it calls through to FAudio which in-turn calls SDL_OpenAudio().

Now, within SDL_OpenAudio, it creates a pa_context which allocates, 64MB (default pulseaudio size) for the shm buffer.

You can now see how very quickly a 32bit application will run out of memory, if these buffers hang
around for any length of time.

How could we reduce the number of pa_context that are created?
Do we really need to open the Audio device multiples times?

Game Gauntlet. When running with xaudio, the game runs out memory when trying to load character selection. Basically the game creates a bunch of IXAudio2 CreateMasteringVoice objects, about 10. For each CreateMasteringVoice it calls through to FAudio which in-turn calls SDL_OpenAudio(). Now, within SDL_OpenAudio, it creates a pa_context which allocates, 64MB (default pulseaudio size) for the shm buffer. You can now see how very quickly a 32bit application will run out of memory, if these buffers hang around for any length of time. How could we reduce the number of pa_context that are created? Do we really need to open the Audio device multiples times?
flibitijibibo commented 2020-03-11 23:49:00 -05:00 (Migrated from github.com)

Do we really need to open the Audio device multiples times?

Yes, to the best of my knowledge this is accurate to the spec. A long time ago I tried to map multiple masters to one device, but lots of performance and compatibility issues arose from that. You can verify the native device behavior by tracing dsound/wasapi calls with the official XAudio2 DLLs.

If they’re trying to create multiple masters at the same time, that should actually be an error:

XAudio2 only allows one mastering voice to exist at once. If you attempt to create more than one voice, XAUDIO2_E_INVALID_CALL is returned.

>Do we really need to open the Audio device multiples times? Yes, to the best of my knowledge this is accurate to the spec. A long time ago I tried to map multiple masters to one device, but lots of performance and compatibility issues arose from that. You can verify the native device behavior by tracing dsound/wasapi calls with the official XAudio2 DLLs. If they’re trying to create multiple masters at the same time, that should actually be an error: >XAudio2 only allows one mastering voice to exist at once. If you attempt to create more than one voice, XAUDIO2_E_INVALID_CALL is returned.
alesliehughes commented 2020-03-12 03:11:50 -05:00 (Migrated from github.com)

Having multiple Master is allowed as long as you use separate XAudio instances which it does for this games. I've dug a little deeper and my estimation was high, its failing on the 5th instance of XA27_CreateMasteringVoice, since it hasn't finished with the other yet, so hasn't called DestroyVoice on the master object.
There appears to be at least one case where the master voice isn't used for anything before it crashes (out of memory).

Having multiple Master is allowed as long as you use separate XAudio instances which it does for this games. I've dug a little deeper and my estimation was high, its failing on the 5th instance of XA27_CreateMasteringVoice, since it hasn't finished with the other yet, so hasn't called DestroyVoice on the master object. There appears to be at least one case where the master voice isn't used for anything before it crashes (out of memory).
alesliehughes commented 2020-03-12 03:40:34 -05:00 (Migrated from github.com)

Maybe we could delay the initialization until first use?

Maybe we could delay the initialization until first use?
flibitijibibo commented 2020-03-12 09:04:42 -05:00 (Migrated from github.com)

Does it work if you set SDL_AUDIODRIVER=dummy? If so then I might actually pin this as an SDL issue (or Pulse?), since we don’t actually control the memory allocations for the platform devices. This may even work when using the SDL WASAPI backend on Windows.

Does it work if you set SDL_AUDIODRIVER=dummy? If so then I might actually pin this as an SDL issue (or Pulse?), since we don’t actually control the memory allocations for the platform devices. This may even work when using the SDL WASAPI backend on Windows.
alesliehughes commented 2020-03-12 14:55:52 -05:00 (Migrated from github.com)

Setting SDL_AUDIODRIVER=dummy, just caused a crash on startup.

Setting SDL_AUDIODRIVER=dummy, just caused a crash on startup.
flibitijibibo commented 2020-03-12 15:08:10 -05:00 (Migrated from github.com)

Right, forgot that you can technically have only one dummy at a time... so unfortunately there’s not an easy way to compare on Linux alone. macOS and Windows would be good places to test this though.

Right, forgot that you can technically have only one dummy at a time... so unfortunately there’s not an easy way to compare on Linux alone. macOS and Windows would be good places to test this though.
flibitijibibo commented 2021-04-20 09:24:36 -05:00 (Migrated from github.com)

Doing a bit of spring cleaning...

This is basically a system issue and is unique to PulseAudio - I would wager a guess that Pipewire fixes this both at the Pulse wrapper level and the direct Pipewire level as well, which SDL 2.0.16 will support. Either way, closing as NOTOURBUG.

Doing a bit of spring cleaning... This is basically a system issue and is unique to PulseAudio - I would wager a guess that Pipewire fixes this both at the Pulse wrapper level and the direct Pipewire level as well, which SDL 2.0.16 will support. Either way, closing as NOTOURBUG.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-FNA-XNA/FAudio#182
No description provided.