• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Leaks and Lies

Status
Not open for further replies.

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,180
Recently a lot of people have been making claims about leaks giving theories and sometimes even evidence to support them. However are they really true?

RemoveUnit() leak
Recently a bunch of people claimed that the native to remove a unit was leaking. They said that killing a unit does not leak and should be used instead. I believed this and supported this as their argument sounded plausable.

That was until I actually bothered to try it out...
I tested all kinds of unit removal I could think of...
RemoveUnit
KillUnit
UnitApplyTimedLife

As killing is not usually instant at removal, I hid the units, made them explode and set their explode graphics to none.

Do they leak leak handle IDs?
In a map with no modified object data I started a timer at map initialization with 1 timeout which ran a function. This function created a footman unit at map origan belonging to player 0 which it then immediatly removed via one of the methods. The map run without any other trigger activity and the handle ID of spawned footman unit was tested before it got removed via a simple line of code inserted into the function. The handle ID displayed remained constant for all itterations. The same was repeated with the explode kill method and timed life method both yielding the same result.

RemoveUnit, killing a unit and letting a unit expire all do not leak handle IDs

Does RemoveUnit() leak memory?
The same setup above was used, this time the timer was reduced to 0.001 seconds (about 1000 itterations a second) and code inserted to stop at 100000 itterations. The map was tested with WC3 in window mode with task manager used to monitor the various working set and commit sizes of WC3 (what is loaded into active memory) to detect for memory leaks as the code runs. All 3 types of unit removal were tested.

The results showed a memory leak of some form that was persistant between all 3 types of removal even down to approximatly the same quantity of data leaking.
This means that creating units or the global dealocation of units must leak no mater how it is done with triggers. After creating 100000 units at 1000 units a second only a couple of MB leaked meaning the leaked can be ignored mostly. Creating 100000 unique strings leaked more than 100000 units. The crash related to the unit leak has not been investigated.

Interesting Note
Handle IDs get recycled perodically (about every 5 mili seconds or 200 times a second from a rough test) rather than as they become freed.
 
Last edited:
Level 20
Joined
Jul 6, 2009
Messages
1,885
If you overwrite a point variable, it generates a leak, right? What if you overwrite a unit variable?
Overwritting a point variable doesn't really generate a leak, it just overwrites it's pointer and if there's no other pointer for the same location, you won't be able to reference it thus it will leak.
Overwriting a unit variable doesn't leak since you can always refer to units and you don't recreate units each time you use them.
 
Level 23
Joined
Jan 1, 2009
Messages
1,608
As you might have seen in GeX' test the Memoryusage varies a bit from test to test, so you should at least test it a few times with the same native.
Also the map/callbacks itself generate some memory usage, probably your "some form leak" was even smaller.

And why didnt you just test nulling right away? or has someone allready done that?

As seen in gex' test groups still leak without nulling, with nulling they leak nothing.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,180
I tested the same results multiple times and they all yielded approximatly the same leaks.

Inorder for handleIDs to be recycled, you need to null all variables that pointed at an object. Local handles need to be nulled or else they will cause a counter leak blocking a handle from ever being recycled but parameters do not although they do act as locals. Unit events do not lock up a unit handleID from being recycled but the events linking to a recycled unit will only be freed when the trigger is destroyed.

Destroying a trigger is apparently perfectly safe as long as the trigger is not running (no active occurances).

Destroying triggers does not leak.
Running a perodic jass function 1000 times a second for 100000 itterations does not leak.
Unit events do not leak.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,180
One could probably prevent that from happening by disabling the trigger and then destroying it at a later time (where all queued instances will have logically run). Atleast that would seem logical but JASS is not the most logical of languages.

It is interpreted. This means that doing something stupid like...
set DrSuperGood = DrSuperGood + 1 //DrSuperGood is a local integer
will itterate through all characters of DrSuperGood 4-8 times while it does various checks and hashes.

One would have imagined taking the effort to atleast translate all unique names into unique ID numbers which could have saved vast amounts of time running JASS code.
 
Status
Not open for further replies.
Top