Hi, I issue a problem:

https://github.com/godotengine/godot/issues/55027

My difficulty is to not be able to debug where the problem is.

I use VSCode as editor and I'm able to do debug code (c#)

Any hint? It will be nice if we can breakdown this voice in editor:

Thanks

ps.: I tried already --verbose tag but without avail :(

I suspect it is due to calling "Dictionary GodotDict = new Dictionary() { ["A"] = "1" };" within your process loop, which in turn is generating a new Dictionary object every 1/60th of a second (then overwriting the reference 'GodotDict' to point to this new object in memory).

The below achieves the same effect as your code without the overhead cost of calling new repeatedly:

namespace Namespace
{
    public class t : Spatial
    {
        public System.Collections.Generic.Dictionary<int, Dictionary> SystemDict =
             new System.Collections.Generic.Dictionary<int, Dictionary>();
        Dictionary GodotDict = new Dictionary();
        public override void _PhysicsProcess(float delta)
        {
            GodotDict["A"] = "1";
            SystemDict[1]= GodotDict;
            GD.Print(SystemDict[1]);
            GD.Print(GodotDict);
        }
    }
}

I would guess that eventually GC would kick in so this may have been a non-issue in practice but idk tbh. Still pretty noob with C# :S

The minimal project I posted - the second one https://github.com/godotengine/godot/files/7554191/TestDictionary.zip - Use GodotDictionary and there is no leak afik. Even so I changed all dict in real code - see code posted in issue - as GodotDict but no avail so far.

And I did find the same problem in Client side ( my project is a client-server game). Where I have the same leak when I call a rpc to the server like: RpcId(1, "MethodOnServer", godotDictionary); If I comment the rpc call I have no leak at all in client...

I opened a issue too https://github.com/godotengine/godot/issues/55086 My opinion its an issue related to a rpc call (network).

Unless I'm missing something your second project looks to have exactly the same problem I highlighted as the first and the solution is likely the same.

If you call 'XXX = new Dictionary()' the constructor allocates the memory for a new Dictionary object, then updates the 'XXX' reference to point to this location in memory.

Running the exact same command a second time, which is what you're doing by running it in _PhysicsProcess, will not automatically free the original memory space. It just allocates a new portion of memory to hold the new Dictionary object, and updates 'XXX' to point at it. The previously reserved memory STAYS reserved until Garbage Collection occurs, which is 'if it needs to' rather than all the time.

This to my knowledge is not related to Godot, but is rather base behaviour in I think many languages including C#, and is normally a non issue as automatic garbage collection (when your running low on ram) will clean it up or can be resolved manually by calling the garbage collector if you want to micro-optimise.

However it is also probably a bad idea in general to use 'new' to recreate an object when all you need is to reuse (or .clear()) the existing object.

;tldr Don't re-instantiate new objects if all you need to do is .clear()/reuse existing ones.

As I said before I was talking about this code (Its possible you missed?) "Even so I changed all dict in real code - see code posted in issue - as GodotDict but no avail so far." SERVER SIDE:

public static Dictionary<int, Dictionary> playerStateCollection = new Dictionary<int, Dictionary>();
  [Remote]
     public void ReceivePlayerState(Dictionary transform)
     {
         int playerID = GetTree().GetRpcSenderId();
         int result = playerStateCollection.Count(p => p.Key == playerID);
         if (result > 0)
         {
             if (Convert.ToUInt64(playerStateCollection.First(p => p.Key == playerID).Value["T"]) < Convert.ToUInt64(transform["T"]))
             {
                 playerStateCollection[playerID] = transform;
             }
         }
         else
         {
             playerStateCollection[playerID] = transform;
         }
         Log.Print(Log.DEBUG, Log.WHITE_BOLD, transform, "  <--->  ", playerStateCollection);
     }

CLIENT SIDE:

RpcUnreliableId(Network.ServerID, "ReceivePlayerState", transform);

RpcId(Network.ServerID, "ReceivePlayerState", transform);

its this one that leak. Not the one in zip file.

Leak client side AND server side.

Its more clear now? :))))

Can you share a zip to reproduce like you did the previous and will have a look.

What MBTI personality do you have? (Don't worry its related ;) )

Chaotic Neutral?

Whatever type thinks personality tests hold as much weight as horoscopes lol

8 days later

In battle field can exist peace?

Anyway back to topic: I'm going to be focused in rust rather an wrong coupled system(GC + not GC) :)

a year later