amazon-chime-sdk-js
amazon-chime-sdk-js copied to clipboard
DeviceController audio memory leak
What happened and what did you expect to happen?
I was profiling a simple React component that only imports the chime JS sdk. It simply creates a new DefaultDeviceController when mounted, and calls the .destroy()
method on unmount.
It seems that AudioBufferSourceNode
persists and a new one is created every time the component is mounted.
This was discovered using heap snapshots in Chrome.
Heap snapshot of initially unmounted component that is mounted and unmounted, repeated twice (Unmounted, Mounted, Unmounted, Mounted, Unmounted):
Have you reviewed our existing documentation?
Reproduction steps
- Create a new
DefaultDeviceController
- Call
.destroy()
on the created instance - Create a new instance of
DefaultDeviceController
again - Memory leak is observed with an additional
AudioBufferSourceNode
Amazon Chime SDK for JavaScript version
2.17.0
What browsers are you seeing the problem on?
Chrome
Browser version
94.0.4606.71
Meeting and Attendee ID Information.
No response
Browser console logs
N/A
Hi,
I tried with creating a DefaultDeviceController
with const _deviceController = new DefaultDeviceController(this.meetingLogger);
in the meeting Demo login page and used the heap snapshot to record the resources generated, but I didn't find AudioBufferSourceNode
that was created. I just wonder what is your implementation for creating the DefaultDeviceController
, did you select a audio device when you create it?
Hi @ldai1 ,
No audio device was selected. Here is another example, I opened the meetingReadinessChecker app and replaced it with the following code:
import { DefaultDeviceController, ConsoleLogger, LogLevel } from 'amazon-chime-sdk-js';
window.addEventListener('load', () => {
const test = async () => {
let logger = new ConsoleLogger('SDK', LogLevel.DEBUG);
let controller = new DefaultDeviceController(logger);
await controller.destroy();
controller = undefined;
// to observe audio node creation
//controller = new DefaultDeviceController(logger);
//await controller.destroy();
//controller = undefined;
};
test();
console.log('test');
});
A source node will be created to generate a tiny amount of noise if an empty audio device is selected:
https://github.com/aws/amazon-chime-sdk-js/blob/5666d7d8370f51eac9f7794b554a0cc54a0b7da2/src/devicecontroller/DefaultDeviceController.ts#L1024
These are supposed to be garbage collected. Did you force a GC before taking the heap snapshot, @Nanosync?
Hi @richnew10, yes a GC was forced, but the object persists in memory.
I am running into the same issue. I am not using using the React components but rather using the SDK in an Angular app. What I discovered when trying to figure out why the memory in our app was increasing after every meeting is that the "AudioBufferSourceNode" objects were being created during the teardown of the meeting. Initially followed the convention used in the examples for tearing down by calling MeetingSession.audioVideo.chooseXXXDevice(null)
. The chooseAudioInputDevice(null)
is creating a the empty audio device. Next tried calling MeetingSession.destroy()
, which is not documented anywhere, instead of calling chooseAudioInputDevice(null)
. This resulted in the same behavior because it is doing the same thing.
Overall there needs to be a short circuit when calling chooseAudioInputDevice(null)
during destroy
so it does not create new resources that are never cleaned up. The following reference is what is creating the empty device during destroy.
https://github.com/aws/amazon-chime-sdk-js/blob/17a5fc7163cf020deeaa90ff45ee414188504862/src/devicecontroller/DefaultDeviceController.ts#L1465
@emopti-jrufer Hi, thanks for providing such a detailed observation. We are working on a fix now.