Animations are leaking memory in obscure situations

One of my team’s games is experiencing Animation category memory leaks - it’s consistently the fastest growing category reported in dev console. Servers only last about ~17 hours and it’s hurting metrics. Older servers need to be joined to see this.

There is no way to break down memory usage by animation ID in dev console, so it’s very difficult for me to pinpoint what is causing this.

I’ve tried rapidly respawning NPCs and players mid-animation, simulating AnimationTrack event connections without disconnection, but I can’t reproduce it - memory clears up correctly in those simulations.

I verified that there are a normal amount of Animator (and their running track counts) and Animation descendants in the DataModel, so they always seem to be destroyed correctly.

Expected behavior

The category should stabilize, not increase indefinitely.

12 Likes

Thanks for the report, we’ll start an investigation into your bug.

2 Likes

Bump, it still is the fastest growing category in the console, like OP said, we can’t track down which asset is causing this because we can’t see the IDs like in the Sounds category, any updates on this?

3 Likes

Also noticing for our game.

Animation memory rises to about 2gb or so, causing us to go over the 6gb memory limit.

Same as OP, I’ve tried replicating it by respawning characters many times to no avail.

Possibly something wrong with our code, but I can’t figure it out.

1 Like

Baseplate demonstration of memory accumulation caused by animations loaded for disconnected players:

https://puu.sh/JXZAa/773685ab02.mp4

I could speculate as to a cause but what’s the hope without the codebase. I may have my own server memory leaks in my game, but the rising star is always Animations. For now I will minimize LoadAnimation calls, to uncertain efficacy. Calling :Destroy on AnimationTracks does not seem to help, not that I thought it would.

2 Likes

I don’t think you’re seeing a memory leak here. Internally, the engine holds an LRU cache for all AnimationClips. This cache will get flushed if it exceeds a certain memory size and you’ll pay the cost of loading and unloading clips at that point, however, the numbers you show on the graph are far below that threshold.

Here is a more extreme case of cloning a R15 rig of myself and playing every animation, then deleting the rig and repeating it. Seems to hang onto over 150MB in the recording, 370MB now that I wrote this out.

Should memory clear in this situation? I don’t know the thresholds for MB, time, or the conditions for cache flushing. I know in my actual game, Animations can reach nearly a GB, proportional to the amount of player sessions.

Does the behavior persist if you keep track of the AnimationTrack instances and explicitly destroy them once you clear the character?

Behavior persists with that revision:
RobloxStudioBeta_2024-01-23_14-23-17

1 Like

Still noticing this for our game.
Rises to 1.5GB or so. If that’s the cache, then it should be cleared much sooner.
Animations shouldn’t take up 25% of the total memory limit (6.25GB).

1 Like

I can attest to this. When is this going to be fixed?!

Thanks for your feedback!
In the past week we’ve made changes to the way Animation memory is cached in the game.
Are any of you continuing to see unbounded growth?

2 Likes

I haven’t checked; I will let you know when I do. @NiceDrift @apenzijncoolenleuk1 @EcceDees may be able to tell you on their circumstances though.

1 Like

Thank you very much for the changes.

Seems to be fixed.

Checked a couple servers with 20-40h uptime (was near impossible to reach before), and all had their server animation memory limited to ~200MB.

Wow only took 6 months to be patched since the initial post, thanks Roblox!

Animation memory behavior is performing identically to my prior test, still getting monotonic growth seemingly endlessly:

This is accomplished using the following script (assuming workspace.Rig):

R = workspace.Rig
R.Parent = nil

while true do
	local rig = R:Clone()
	
	rig.Parent = workspace
	
	local animator = rig.Humanoid.Animator
	local ats = {}
	
	for _, sv in rig.Animate:GetChildren() do
		local anim = sv:FindFirstChildOfClass("Animation")
		if anim then
			local at = animator:LoadAnimation(anim)
			at:Play()
			table.insert(ats, at)
		end
	end
	
	task.wait()
	
	rig:Destroy()

	for _, at in ats do
		at:Destroy()
	end
end
2 Likes

Thankyou for you feedback!
What kind of animations did you use to produce this behavior, ordinary character animations or huge, long lasting ones?
How many different animations did you use?
We have not succeeded in replicating these results using default avatar animations.
Thanks again!

RobloxStudioBeta_2024-03-03_20-09-25
Just the default animations contained when using “Rig Builder”

animation_memory_leak_model.rbxm (30.6 KB)
Just ungroup this model in a fresh baseplate.

1 Like