Hi Livekit team,
I found a memory leak in the RTC engine of Livekit that causes memory consumption in the browser to grow if you publish / unpublish screen shares in a loop under some special circumstances ( stopOnUnpublish: false )
This is easily reproducible in “meet.livekit.io ” (simply start a meeting and start/stop screen sharing in a loop to see the memory leak).
I have a proposal to fix this in a PR here: Reuse inactive publisher transceivers in RTCEngine to reduce memory growth on republish by moufmouf · Pull Request #1827 · livekit/client-sdk-js · GitHub
I know you must have a ton of work already, but I wanted to give this PR a chance to be properly reviewed, as it would probably save some RAM to many users.
Thanks a lot for your hard work!
main ← workadventure:reuse_transceiver
opened 07:27PM - 27 Feb 26 UTC
## Why?
I'm developing WorkAdventure, a virtual space platform and we use Liv… ekit for big meetings (more than 4 participants). Under 4 participants, we use a direct P2P mesh. I'm telling this because we have a workflow where we manage the MediaTracks (they are created by us, not Livekit JS client SDK) and when we unpublish a track, we usually set `stopOnUnpublish: false` when calling `localParticipant.unpublishTrack`.
The issue that triggered this PR is that when we start publishing a screen sharing, the memory goes up by about 400MB. We stop publishing the screen sharing with `localParticipant.unpublishTrack`, the memory does not go down. We start publishing another screen sharing again (maybe another window), the memory goes up by another 400MB, etc...
In short, we have a memory leak, where each started screen sharing is never releasing memory.
As a side note, using `track.pauseUpstream` to stop the track then replace the track with another track later seems to work better, but this workflow causes other issues (like the fact that egress CompositeRoom will display a black box for a paused video instead of not showing it at all)
## Finding the memory leak
I tried to track down where the memory leak was, and after a few trial and errors (and with the help of Codex), I ended up finding that the transceivers in the `RTCEngine` seem to be piling up each time we start a new track. The `RTCRtpTransceiver` seem to hold a reference to the `MediaTrack` that is never freed and eating a lot of memory. I did not find any way to properly free the `MediaTrack` reference, but Codex (again) proposed me the patch below. Basically, it tries to reuse an inactive existing sender that shares the same track "kind".
I tested this with WorkAdventure and the patch works. When I stop / start many screen sharing many times, the memory does not pile up. I also re-read the patch and validated it myself (to avoid any AI slop).
Note: I tried an alternative: freeing the memory as soon as `localParticipant.unpublishTrack` is called (using `replaceTrack(null)`) instead of waiting for the next track to start to reuse the transceiver. Alas, I could not make this work (that would be ideal as the memory would be freed as soon as we finish publishing... here, we have to wait getting out of the Livekit room for the memory to be freed)
What do you think of this patch? I can happily work on it if it needs any improvement.
Thanks David, I have raised this with the client team to see if they can take a look.