Search Unity

Question Netcode dictionary memory leak issues

Discussion in 'Netcode for GameObjects' started by splundge, Mar 22, 2024.

  1. splundge

    splundge

    Joined:
    Dec 29, 2021
    Posts:
    24
    Hey I found the dictionary example from
    https://github.com/Unity-Technologi...untime/NetworkDictionary/NetworkDictionary.cs
    but it's not compatible with the last version of netcode.

    I've fixed it up to be compatible with 1.8.1 (just changed some properties and it worked):
    https://pastebin.com/3BiM5Yyp

    But when i use it (in a NetBehaviour), unity complains that there's a memory leak:
    "A Native Collection has not been disposed, resulting in a memory leak" x4, pointing to these 4 properties
    Code (CSharp):
    1.  
    2. private NativeList<TKey> m_Keys = new NativeList<TKey>(64, Allocator.Persistent);
    3. private NativeList<TValue> m_Values = new NativeList<TValue>(64, Allocator.Persistent);
    4. private NativeList<TKey> m_KeysAtLastReset = new NativeList<TKey>(64, Allocator.Persistent);
    5. private NativeList<TValue> m_ValuesAtLastReset = new NativeList<TValue>(64, Allocator.Persistent);
    6.  
    It LOOKS like they're being disposed in the `.Dispose()` function... Is there some other way that this custom network variable needs to be diposed in 1.8.1 ??
    Do these even need to be native lists? Why can't they just be regular managed Lists ?
     
  2. splundge

    splundge

    Joined:
    Dec 29, 2021
    Posts:
    24
    Here's a super simple, cut down example that shows the memory leak... shouldn't this be fine??
    Code (CSharp):
    1.  
    2. public class ExampleNetworkVariable<TKey> :
    3.     NetworkVariableBase
    4.     where TKey : unmanaged
    5. {
    6.     private NativeList<TKey> m_Keys = new NativeList<TKey>(64, Allocator.Persistent);
    7.     public override void Dispose()
    8.     {
    9.         m_Keys.Dispose();
    10.         base.Dispose();
    11.     }
    12.     public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta)
    13.     {
    14.     }
    15.     public override void ReadField(FastBufferReader reader)
    16.     {
    17.     }
    18.     public override void WriteDelta(FastBufferWriter writer)
    19.     {
    20.     }
    21.     public override void WriteField(FastBufferWriter writer)
    22.     {
    23.     }
    24. }
    25.  
    if you use it in your code anywhere, the editor shows this error:
    A Native Collection has not been disposed, resulting in a memory leak. Allocated from:
    Unity.Collections.NativeList`1:.ctor(Int32, AllocatorHandle) (at .\Library\PackageCache\com.unity.collections@1.2.4\Unity.Collections\NativeList.cs:116)
     
  3. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    668
    It looks like NGO will support NetworkVariable dictionaries soon according to this. The PR is already on the develop branch, I had a quick play and the dictionary appears to sync but I don't know how it picks up changes to the dictionary.
     
    CodeSmile likes this.
  4. splundge

    splundge

    Joined:
    Dec 29, 2021
    Posts:
    24
    actually i found the issue. I was initializing the dictionaries in the class like so
    Code (CSharp):
    1.  
    2. public sealed class SampleClass : NetworkBehaviour
    3. {
    4.     ...
    5.  
    6.     public NetworkDictionary<ulong, int> NetworkDictionary = new NetworkDictionary<ulong, int>();
    7.     ...
    8. }
    9.  
    changing it to this seemed to get rid of the memory leak warnings:
    Code (CSharp):
    1.  
    2. public sealed class SampleClass : NetworkBehaviour
    3. {
    4.     ...
    5.     public NetworkDictionary<ulong, int> NetworkDictionary;
    6.     private void Awake()
    7.     {
    8.         NetworkDictionary = new NetworkDictionary<ulong, int>();
    9.     }
    10.     ...
    11. }
    12.  

    But also, good to hear. i think an official network dictionary would be handy
     
    Last edited: Mar 23, 2024
  5. splundge

    splundge

    Joined:
    Dec 29, 2021
    Posts:
    24
    Hmm. The updated code doesnt seem to work. The dictionary does not appear to synchronize itself across the clients (only on the server). I suspect its not triggering because i had to change this code from:

    Code (CSharp):
    1.  
    2. internal void MarkNetworkObjectDirty()
    3. {
    4.   m_NetworkBehaviour.NetworkManager.BehaviourUpdater.AddForUpdate(m_NetworkBehaviour.NetworkObject);
    5. }
    6.  
    to
    Code (CSharp):
    1.  
    2.     internal void MarkNetworkObjectDirty()
    3.     {
    4.         SetDirty(true);
    5.     }
    6.  
    which.. i dont think it does the same thing. The 'behaviour updater' is no longer publicly accessible. any idea on how to fix this for 1.8.1 ?