Unity-Technologies / com.unity.webrtc

WebRTC package for Unity
Other
738 stars 186 forks source link

[BUG]: Memory leak when receiving long-running video stream (iOS, Mac, Linux) #1013

Open kevindude6 opened 6 months ago

kevindude6 commented 6 months ago

Package version

3.0.0-pre.6

Environment

* OS: ipadOS 16.6.1, Mac Ventura 13.4.1, Ubuntu 20.04 (IL2CPP and Mono)
* Unity version: 2022.3.5f1

Unity application connects to a live webrtc stream for long periods of time (>24 hours)

Steps To Reproduce

  1. Connect to a WHEP endpoint streaming a video track
  2. Observe memory increase every hour

Current Behavior

Memory will increase slowly over time (a few MB per 10 minutes) On iPad, once memory limit is reached, the app will close without notification or crash log.

Expected Behavior

No memory leak.

Anything else?

Screenshot from Unity Memory Profiler snapshot comparison

Screenshot 2023-12-15 at 16 09 02

Screenshot from XCode leak profiler (snapshot taken every 10 seconds)

Screenshot 2023-12-15 at 16 05 02

Screenshot of XCode leak info. The 256 byte malloc is occurring at a consistent rate, leading to increased memory usage.

Screenshot 2023-12-15 at 16 06 27

Screenshot of leak callstack

Screenshot 2023-12-15 at 16 16 19

Judging by the callstack, the leaked memory appears to originate from the call to Marshal.StructureToPtr() in Contex.cs::Batch::Submit

(From here on is my conjecture, and I am not an expert in this area, so I may have misunderstood)

Reading the "Remarks" section in the Marshal.StructureToPtr documentation we see:

...All other reference types (for example, strings and arrays) are marshaled to copies. To release these managed or unmanaged objects, you must call the Marshal.DestroyStructure method before you free the memory block.

The BatchData struct contains an IntPtr array, so it might be the case that this array is being copied and never properly freed. I tested by setting the fDeleteOld parameter to true, and the memory leak was resolved (tested on Mac only) I think this is safe because the first StructureToPtr call happens when the Batch class is initialized (with fDeleteOld false, as it should be), and every call after that comes from Batch::Submit(). So the ptr variable will always hold valid data to free.

Please let me know if I can be of assistance in any way.

karasusan commented 6 months ago

Thank you for clarifying the problem.

karasusan commented 6 months ago

memo: WRS-504

kevindude6 commented 1 month ago

Hi, is there any update on this issue? It is causing our application to crash during long use