Short note on garbage collection

Discussions about Coding and Scripting
Post Reply
JackGriffin
Godlike
Posts: 3774
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: -Retired-

Short note on garbage collection

Post by JackGriffin »

When I was working on the weather effects I ran into this bug where particles would not recycle correctly. In trying to fix it I discussed this at length with FeraliDragon. He told me some things I did not know but really matter. Take this code for instance (ripped from the Chaos Mansion):

Code: Select all

	ForEach ZoneActors(class'PCPillarJr',PP)
	{
		if (PP != none)
		{
			PP.Destroy();
			PP = None;
		}
	}
Immediately you see an extra entry into the destroying protocol. Why is it there? Well it turns out that there will be times when it's quite important to force actors totally out of the way, so far out that the only step left is actual garbage collection. By declaring "SomeActor = None" after destroying it removes lingering traces of the destroyed actor and cleanses it as much as you can. By adding this bit of code I was able to fix most of the issues that were happening to the weather effects. I ended up rewriting the entire code though to fix other problems but the validity of this bit of code still stands and should be considered in your own work when manually destroying actors.
So long, and thanks for all the fish
User avatar
sektor2111
Godlike
Posts: 6403
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Short note on garbage collection

Post by sektor2111 »

My thoughts:
Sometimes variables seems to need to be nullified else probably hangs in dependent devs during travel - Testing server having troubles ? I see that Higor was doing this and I did the same in some of those newer tweaks which are operating and then they don't need to mess up with their presence.
Else iterators generally are self sanitized, they don't need "if(PP != None)", iterators are simply dealing with that type of actors automated they will never operate other types than that "BASE".
Garbage collector having that map thing linked with some dude probably will not remove garbage correctly causing evilized fragmentation ? By declaring it None it will go correctly marked for collecting garbage ? Since adding that line doesn't cost a penny I might use it if things must be done this way...

I recall some question about opposite of "new". I'm not only not using "new", because I'm not creating classes, I load classes created, but for sure opposite of "New" should be something like "Self = None" in that class or some outsider controller.
nogardilaref
Masterful
Posts: 577
Joined: Tue Jun 20, 2017 1:00 pm
Personal rank: ⚋⚊⚌☰⚞⌖⚟☰⚌⚊⚋

Re: Short note on garbage collection

Post by nogardilaref »

sektor2111 wrote: I recall some question about opposite of "new". I'm not only not using "new", because I'm not creating classes, I load classes created, but for sure opposite of "New" should be something like "Self = None" in that class or some outsider controller.
As far as I am aware there isn't an opposite of "new" in UScript, exactly over the fact that UScript has its own garbage collector and thus generally languages with garbage collectors do not have operators to explicitly deallocate objects from memory.
In such languages, the "destruction" of an object is generally done by simply nullifying its reference, which depending on the language might be "null" (PHP, Java, C#, etc, used by most languages), "nullptr" (C++), "nil" (Lua) and "None" in the case of UScript.

Therefore:

Code: Select all

//create a new object
A = new class'SomeObject';

//"destroy" object (it only really disappears once it gets garbage collected internally)
A = None;
Note however, that as long as there is one valid reference towards an object, it won't get garbage collected, thus it will never disappear, hence:

Code: Select all

//create a new object
A = new class'SomeObject';

//copy reference to B
B = A;

//unassign from A, but it's not garbage collected as B is still referencing it
A = None;
C++ however has an operator which is the opposite of "new", and it's called "delete".
Given that C++ doesn't have a garbage collector, you are required to "delete" references after you're done with them, or the memory will remain allocated forever and you will end up having a memory leak.
Higor
Godlike
Posts: 1866
Joined: Sun Mar 04, 2012 6:47 pm

Re: Short note on garbage collection

Post by Higor »

Is PP a local variable or a global variable?

EDIT:
That doesn't make a bit of difference in UT99 anyways.

1- Actors aren't removed through garbage collection during gameplay, they're stored in a linked list pending for deletion.
2- Deletion process requires 256 actors pending deletion in order to kick in.
3- Deletion process occurs at end of tick.
4- Deletion process dereferences all Actor variables in Actor types (bDeleteMe=True), therefore you only dereference if the variable is in Object types.
5.1- In default Engine, the actor name resides in the hash forever.
5.2- In XC_Engine the actor name is reutilized for a new actor. (more efficient in servers than in clients)
6- Deletion always deallocates the actor and destroys it's variables, so there's no memory leaks.

In other words, you can spawn actors endlessly in XC_Engine without causing a hash map overkill, and stop worrying about an actor once it's Destroyed() event is done.
If code or whatever other mod's never evaluates for actor's bDeleteMe var after the NONE check, then yes dereference to workaround bad coding.

Code: Select all

if ( Something == None || Something.bDeleteMe )
    TreatAsNone();
nogardilaref
Masterful
Posts: 577
Joined: Tue Jun 20, 2017 1:00 pm
Personal rank: ⚋⚊⚌☰⚞⌖⚟☰⚌⚊⚋

Re: Short note on garbage collection

Post by nogardilaref »

Oh, that's very useful info, cool, thanks. :mrgreen:
Higor wrote: If code or whatever other mod's never evaluates for actor's bDeleteMe var after the NONE check, then yes dereference to workaround bad coding.
Unless I misunderstood what you meant, not doing the bDeleteMe check is not bad coding in itself. The engine is the one which is badly designed in that sense, since you as a developer should never have to do more than 1 single check for what is essentially the same end condition.
The moment you have to check for the same 2 things constantly, to be completely sure the Actor was destroyed, perhaps to the point you have to create a function for it (isDestroyed(Actor A) for example), it's not inherently the developer's fault that the engine is so badly built around anti-patterns.

In other words, yes you have to do it for best results, but you shouldn't really have to.
Higor
Godlike
Posts: 1866
Joined: Sun Mar 04, 2012 6:47 pm

Re: Short note on garbage collection

Post by Higor »

As a matter of fact, as of UT2k3 the following code

Code: Select all

if ( Something == none )
    Etc();
Effectively considers existing actors with bDeleteMe flag set to True as none.
ShaiHulud
Adept
Posts: 459
Joined: Sat Dec 22, 2012 6:37 am

Re: Short note on garbage collection

Post by ShaiHulud »

That's useful to know about. I've done this unconsciously in a few places out of habit from experience with other languages. In those other languages freeing the memory associated with a variable only marks the memory space available for re-assignment and doesn't set the pointer to nil (or null as the case may be), so it can 'look' occupied, but contain meaningless data.
I'm curious about how UnrealScript deals with "dangling pointers". Somehow every class that contains a reference to an object "knows" when the object has been destroyed. Dealing with that has been a source of pain in other languages in the past.
User avatar
sektor2111
Godlike
Posts: 6403
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Short note on garbage collection

Post by sektor2111 »

So I deducted well. Actor A being NONE is NOT Deleted, is pending deletion in a sort nullified state, this happens if is not mentioned by some B referencing it. These bad references are cancerous then, fix me if I'm wrong...
However, like I said, after playing a long period a map like LongCorridor I was thinking that server went stuck. No... it was operational, but being extremely busy with garbage collection, this means it has a lot of stuff to remove in that travel time... eh... so I'm not sure if actor names have been so recycled because it was a large amount of garbage collected, or I'm mistaking here...

Anyway, some tweaks which I do using XC Actors I put them NONE after doing their job - after ReplaceFunction task I followed the sample with "unload" variables class types used and reset to None.

At this moment UnrealI, UnrealShare, BotPack are properly unloaded (by example) and I don't have any trouble when I do screw such some class from them, in next Level everything goes clean - (it was an old discussion about my 3072 map with some tweaks - which was never hurting me).

Aside, garbage collector which I was using some time ago and collecting garbage in game, I had to remove it, I see it a bad idea when game is full of action, I cannot explain what is wrong in good terms, but I have some feelings about what's going on there, so removing garbage in game will never be my way of doing...
Post Reply