About garbage collector efficiency using local variables

Running the game there is a small hitch every 60 seconds (bigger hitch every 30 seconds running in the editor) due to the garbage collector.

My question is about the local variables, which I use in practically all the functions, including the ones that run in each frame like Tick.

What is the impact of these variables that are constantly being created and destroyed in the garbage collector?

Should I declare some global variables, vectors, rotators, floats, etc., and use them in functions instead of declaring local variables? Would this improve the impact of the garbage collector (smaller hitchs)?

I also use local variables in abundance, and often marvel at the seeming efficiency of creating/destroying them during ticks at runtime. Often I’m even creating huge arrays of structs.

I’ve never noticed any slowdown that I could isolate to the use of these variables, so i’d guess it’s not something to worry about.

I would assume they would not impact the garbage collection though. As they are defined local, one would assume they are thrown out at the completion of whatever function they reside. I’d be curious to learn more though if anyone has any further insight.

Have you tried running the STAT SLOW command to report on what may be causing the spikes? You can also disable garbage collection verification by using -NoVerifyGC to verify if it is indeed the GC that is causing the spikes.

https://docs.unrealengine.com/udk/Three/ProfilingBasics.html

Are you ensuring you are doing your own cleanup when destroying actors/classes? It seems strange that the garbage collector would have so much work to do that it would cause a spike.

1 Like

I used the profiling time ago and the garbage collector was the cause. It ocurrs exactly every 60 seconds and produces a small peak (in editor is every 30 seconds and higher peak). I have not tried yet with the game cooked.

-NoVerifyGC seems to not work because the result is the same.

I have two things I need to improve. The game is creating & destroying constantly the foliage grass when the player moves, and also can be about 150 NPCs walking around the player, when they are far are destroyed and a new one is created in another place. I have plan to use a pool to reduce the creation/destruction of them.

But I have a test with and without NPCs and grass, and the peaks persists. Here with:

And without:

and the peaks are similar. In the second image there are nothing creating or destroying, the day/night cycle is stopped… so I don’t know what makes the GC to work so hard.

That’s why I thought they could be the local variables in tick functions. But… the peak when there are only one Pawn should be smaller than when there are 150 Pawns.

About the cleanup do you refer to set none all the variables referenced to the animtree when the actor is destroyed? There are more things to do?

I just mean that if you have spawned actors from other actors, to make sure you destroy them (before setting their ref to none). Otherwise they dangle in memory until the GC inspects them to figure out if any other resource is referencing them. If nothing is referencing them, then the GC destroys them.

Personally if I was you, I would start eliminating elements from your scene to catch what it is that is causing the spike. For instance, if you start your game on a completely empty default UDK map (running your game code), does the spike still occur?

Yes, with a default map even using UTgame.

I have to test with a cooked game to see if it ocurrs too.

That is very unusual. I don’t experience any such hitching on my game, and I have many 100’s of thousands of actors on the map.

Which version of UDK are you using?

The latest version, 2015-01.

in your log does is say anything about the GPU and it being delayed by 500ms?

Also make sure you do not have a timer firing over and over that should not be. That will cause lag spikes. I had a timer set to true, i had coded it wrong and every time it fired it would cause a lag spike.

I guess the next thing I would try is a default UDK install and see if the lag spike is present. In which case, this would be a fundamental issue with UDK (or perhaps an issue with hardware you’re running it on). This seems unlikely, but probably best to check before you go down a debugging rabbit-hole.

Gamepainters, I had that problem with the (exactly) 500 ms in an old PC, when using two monitors. I remember it was corrected by returning to an older nvidia driver. In the PCs that I have now it does not happen.

I use a lot of timers, but they don’t seems to be the problem.

you are right, I think I have to test it in a new UDK installation, because in the current I have the problem even using a blank map with UTgame.
Maybe it is some parameter of the ini, which I modified a lot to do tests.
I have a copy of the inis before modifying them, I’ll test that before doing a new install. And I will tell you the result.

Thank you both for your help.

@ CobaltUDK How often does this happen? Does it repeat every so often? like say every 20 seconds or is there a pattern to it? If so check your true timers set for that repeating time. If it is a timer you will find it that way.

Every 30 seconds, but I haven’t any timer of 30 seconds. And that happen even in a blank map using UTgame.
I think it’s any modification I did in the config files. I will try with a new UDK installation.

by now I suggest you try it with a cooked game and rule that out

@ CobaltUDKThat sounds like the GPU 500ms lag time. It was happening every 30 seconds or it did on my setup. That was caused by old drivers or old hardware, as you pointed out. Yeah, do a fresh install of udk and see what happens.

Edit: After reading what UnrealEnterprise put up i bet that is your problem.

Edit: Thought just came to me, are you experiencing this on any other games or software? If so, you have hardware issue getting ready to really show up. Check for bad caps on mother board and smps. If you see that then that is your issue. Also check your fans for being plugged with dust, that will cause what you are describing as its causing the ics to get to hot.
Usually the 1st sign of bad caps are, when caps start to go bad is repeating lag type spikes(dirty voltages leaving ac on the dc line and getting into the chips(not good for the chip, it causes it to get to hot and possibly chip damage, which results in lag type spikes)). until they get real bad and the lag will get worse until whatever it is goes out for good.

I think is not the 500 ms GPU problem. I had this in an old PC, but now the peaks are much shorter.

I have tested it in two PCs and in both there are peaks:

  • PC with Win7, i7 4790K + GTX 970.
  • Laptop with Win10, i7 10870H + GTX1660 Ti.

I think is a problem with my UDK installation (with UTgame in a blank map ocurrs too). I’m going to try with a new installation, and with a cooked game as said, if I can solve memory problems.

Figure out the problem?

Not yet, but I plan to test in the next few days.

I’ll start by updating drivers and restoring the config files.
The next step will be to test in a new UDK installation.
And if it doesn’t work, I’ll try with an older UDK version.
I have 3 pcs where I can test, with different OS and cpu & gpus.

I will tell you here the result.

I have removed this from ini’s, so I can confirm that the garbage collector is the cause of the peaks.

Suppress=DevGarbage

From the log, running the stand alone game (not cooked) in the map game with about 1100 pawns.

[0081.10] DevGarbage: Collecting garbage
[0081.14] DevGarbage: 46.406791 ms for realtime GC
[0081.15] DevGarbage: 3.121443 ms for unhashing unreachable objects
[0081.18] DevGarbage: GC purged 1097 objects (320302 → 319205)

[0111.10] DevGarbage: Collecting garbage
[0111.14] DevGarbage: 43.822400 ms for realtime GC
[0111.15] DevGarbage: 2.221245 ms for unhashing unreachable objects
[0111.18] DevGarbage: GC purged 0 objects (319205 → 319205)

[0141.12] DevGarbage: Collecting garbage
[0141.16] DevGarbage: 43.819640 ms for realtime GC
[0141.16] DevGarbage: 2.217483 ms for unhashing unreachable objects
[0141.20] DevGarbage: GC purged 0 objects (319205 → 319205)

The GC takes almost 3 frames (43 ms) to do it’s work, even there are no objetc to purge.

Seems that the problem is to iterate all the objects because there is no big difference when 0 objetcs are purged. There are 320000 objects in this map, but using the UDK default map there are about 115000 objects and the peak is about 16 ms.

So, there are some way to reduce this, marking objects as no GCable or something?

I assume that static meshes have bmovable = false and bnodelete = true, but this affects to GC?

There is any way to do the recollection distributed in several ticks instead do all it in a frame?

do you have these comments in your player controller file?
// “force garbage collection while dead, to avoid GC during gameplay”
or
// “force garbage collection when possessing pawn, to avoid GC during gameplay”

Yes, these are in UTPlayerController.

Only does a “WorldInfo.ForceGarbageCollection(bool);”, I have tested this function manually, and only does a CG in that time.

But it does not prevent it from doing it every 30 seconds. I think that these lines are to force a GC in some moments, for example when you enter or exit from a menu or pause, to minimize the hitching.

According to the Epic documentation, it is impossible to avoid GC, but you have to try to have the minimum number of objects to check so that the peak is not too high.

Currently I have about 300,000 objects in the map, the peak is about 45 ms. But in a blank map with UTgame there are 115,000 objects and the peak is 16 ms, for only a floor and a cube meshes (was a surprise for me to see the high number of objects in the world).

1 Like