Parenting objects to PlayerGui from the server leaking memory

I came across this bug trying to figure out a way of transfering models from the server to a client without any other client knowing about the transfer. FE is on.

The bug happens as follows:

  1. Client asks via RemoteFunction for a copy of the model
  2. Server responds by copying the model from ServerStorage, parenting it to their PlayerGui, and then returning the model
  3. Client now has the model reference and destroys it after its arrival
  4. The memory taken up by the model is never released on the client

Repeating the process every second shows a constant rise in memory usage. Requesting the server to clear the client PlayerGui removes any server references to the objects but still fails to release client memory used by the transfer model(s). Resetting your character does not clear the memory used either.

You can view this behavior by joining the following place and observing your memory usage via performance stats. All you need to do is stand there and watch numbers, you should see it constantly rising as the steps above happen every second. A file copy of the repro place is attached to this post as well.

playergui memory leak repro.rbxl (50.0 KB)

I’ve been able to repro this behavior 100% of the time in a published place and in studio via Starter Server + 1 Client. This bug does not occur when testing in studio via PlaySolo.

20 Likes

Can confirm that this issue is 100% reproducible when done as WhoBloxedWho says.

3 Likes

There needs to be a better way to do this. My entire game’s system is based on the idea that data should be sent on a need-to-know basis

8 Likes

Selective replication would be amazing. Writing my own serializing for my use case just seems largely inefficient compared to being able to just pass an object reference.

6 Likes

Thanks for reporting this issue. An internal bug report has been filed.

9 Likes

Aw heck, I was just about to make a zone loading system and came upon this bug. I’d love to know when it gets fixed, if at all possible. This is a bit of a pain because it halts a lot of my plans.

1 Like

Robloxian Highschool uses the PlayerGui to do some custom asset streaming

2 Likes

Hello, Roblox dev here

The problem with the sample code is a race condition. The LocalScript line to destroy the cloned object ‘transfer:Destroy’ is occurring before the RemoteEvent:FireServer is serviced (the event is not processsed immediately), which results in passing an orphaned client-side instance as the event argument. There will be no effect when the Script attempts to Destroy it on the server. Another clue of a race condition here is that the problem does not occur locally, since there is essentially 0 latency between the client and server when running locally, which hides the issue introduced by using an asynchronous event call.

There are several ways to adjust this sample to a non-leaking state. Here are a couple simple approaches to highlight the issue.

  1. Don’t call Destroy on the client side object. There shouldn’t be any reason to do this here, since the server Destroying the Instance will also remove it from the client. If the event argument has not been Destroyed then the server should be able to reconcile the target Instance and Destroy it.

  2. Use a second RemoteFunction (Synchronous) in place of the RemoteEvent (Asynchronous). This will ensure the ‘transfer’ argument passed to the server will still be valid by the time the server script tries to destroy it. If a RemoteFunction is used, the ‘transfer:Destroy’ can remain, but still shouldn’t be necessary as discussed in point 1.

You should notice the leak does not occur when either of the two examples are employed.

This was my finding from looking at the sample source directly. If this isn’t a satisfactory explanation or you feel it’s erroneous I will investigate further into the engine source.

Thanks.

9 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.