Triggers - Memory Leaks

Rad

...
Reaction score
228
[highlight]
Memory Leak Tutorial
By - Rad​
[/highlight]


What is a Memory Leak?

A memory leak is a small bit of information that is not removed after it is used. Converting anything to a non-official variable can cause a memory leak. Point leaks are using center/random points in memory leaks. Group leaks are when you use a unit, player, or destructible GROUP function (Without variables for the group). Region leaks are whenever you convert a 'point with size' or an area, that is not already a variable or preset, to a region.


Symptoms of a Memory Leak:
  1. Server Splits
    .....Server Splits happen whenever alot of memory leaks are detected, they can be very random or always happen at the same time. They can range from everyone except you disconnecting, to having a few players disconnect. If you can find out if the disconnected players are still in the game together then that is solid proof of a server split.
  2. Heavy Lag
    .....If your map starts lagging, usually over time, first check to see if something wrong with a trigger. Say you spawn one skeleton every second of the game, it wont lag for awhile but if you dont kill them off it will. A good way to test is have a -killall trigger to check if they are simply overspawning. If this doesnt help, its probrably a memory leak.
  3. Random Disconnections
    .....First make sure they are not just leaving, secondly if everyone except you leaves at once, it can either be you randomly disconnecting or a server split. As I said its nice to stay in contact with those who disconnect just to check.
  4. Slow Performance
    .....If its not exactly laggy, but is running unusually slow... ask the other people in your game if it seems slow. As long as there isnt a problem spawning or something that can effect your video/sound card to create lag its possible that its from a memory leak.
  5. Triggered-Spell Lag
    .....Not only for spells, but any trigger that has alot of possible memory leaks (List below). If it happens when this fires, and your sure of it, use this tutorial to get rid of as many as possible!


Types of Memory Leaks:

- Points: These are the most dangerous when making spells and movement systems with keyboard. Whenever you use the position of an object or a point of a region (Whether it be random or center), and even coordinates, they create a memory leak.
- Groups: Also a common leak, whenever you use "Unit-Group - Pick every unit..." (Also Player and Destructible etc) and you do not use a variable as the group, it will leak.
- Regions: Converting a point with a size to a region, or anything that creates an 'area' without using a region (or preset) will create a memory leak.
- Special Effects: If you do not remove a special effect (Done through a trigger, spells do not leak) it will leak. Even if the spell is finished, the data is still there.
- Strings: Strings are very minor, as they are reused. Once you use "Hi" as a string, every time you use "Hi" it uses the same data, it will not leak... but if you display random messeges (Tips that are preset are fine) it might add up, but probrably not...


Restoring the Memory:

Points: The easiest way to remove a point leak is by using a universal point variable. As long as there are no waits which seperate the declaring of the variable to the use of the variable you only need one variable. If you do use a wait you need a seperate global - If not another trigger may remove its data before it is used.

Leak:
Code:
Unit - Create 1 footman at (Center of (Region A)) for Neutral passive facing default building degrees
Fix:
Code:
Set Point = (Center of (Region A))
Unit - Create 1 footman at (Point) for Neutral Passive facing default building degrees
Custom Script: call RemoveLocation(udg_Point)

Groups: These are fairly easy to remove, so long as they do not use waits as well. It was suggested to only use waits in integer loops by a few people higher than me.

Leak:
Code:
Unit Group - Pick every unit in (Units owned by (Player 1)) and do (Unit - Kill (Picked unit))
Fix:
Code:
Custom Script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units owned by (Player 1)) and do (Unit - Kill (Picked unit))
NOTE: To remove player group leaks, replace "Group" with "Force".

Fix 2: More efficient
Code:
set UnitGroup = (Units owned by (Player 1))
Unit Group - Pick every unit in UnitGroup and do (Unit - Kill (Picked unit))
Custom Script: call DestroyGroup(udg_UnitGroup)

Regions:
Regions are usually very minor leaks, unless you customize your spells like War Stomp they shouldnt be a problem. You should only need one variable for these, as they are not as needed to store.

Leak:
Code:
Unit - Cause (Casting unit) to damage ((Point) with size 500, 500) dealing 500 damage using attack type Normal and damage type Normal
Fix:
Code:
Set (Region) = (Point) with size 500,500
Unit - Cause (Casting unit) to damage ((Point) with size 500, 500) dealing 500 damage using attack type Normal and damage type Normal
Custom Script: call RemoveRect(udg_Region)
NOTE: Point would be a variable as this would leak both a point and a region (Like most region leaks)

Special Effects:
These are easy to fix, just destroy the effect with the GUI function "Destroy Effect", you may need a variable for this. It will still display its death animation, if it has none it will usually last roughly 5 seconds.

Leak:
Code:
Special effect - Create special effect at (Point) using (Units\Human\Footman\Footman.mdx)
Fix:
Code:
Special effect - Create special effect at (Point) using (Units\Human\Footman\Footman.mdx)
Set (Footman Effect) = (Last Created Special Effect)
Wait 5 seconds
Special effect - Destroy (Footman Effect)
NOTE: If your effect shouldnt disappear, sacrifice the memory leak... just dont use to many!

Strings:
You cannot do anything about string variables (To my knowledge), if you can I'm sorry I do not have the answer.


FAQ's:

.....How do variables help?
Using a variable to store a piece of information is the only way to call upon that information in order to remove it. Sometimes they are automatically stored, example the (Last created...) function will store the information, and you do not need a variable. You still need to remove the (Last created...) after use, though.

.....How do you use the function tags?
Most, if not all of the memory leaks have a different function tag. They all basically use [highlight]call Remove"Function"(udg_Your_Variable)[/highlight] (Also [highlight]call Destroy"Function"(udg_Your_Variable)[/highlight] and with this, you can find a JASS tool that has a list of function names and find out how to remove them yourself!

.....What are some guidelines to reducing memory leaks?
Memory leaks are most common when using periodic events, especially small ones such as (Time - Every .01 seconds of the game). Keep in mind using such a small value means that your FPS is higher than 100 with that event, most peoples arent... if they are they would hardly notice if you used (Time - Every .05 seconds of the game). It might not seem much different, but .01 happens 5 times more than .05, and you cant tell the difference anyways!

Also, using groups (mainly unit groups) are common memory leak generators. Theres a solution above, of course.

.....How do I check if my triggers leak?
If your trigger uses a periodic event under 5.00 seconds, then you need to check for any of the common leaks (Listed above). Also check ones with any group or integer loops. Spells are also very common, mainly for leaking points... so double check those too. Its a good idea to use the Object Manager (F11) to find where functions loop or you use unit/player groups.
 

emjlr3

Change can be a good thing
Reaction score
395
lol I just posted one of these :p
 

Yoshii

New Member
Reaction score
74
you forgot 1 thing , what a memory will actually do to your map?why is it bad?
Code:
call DestroyForce(GetLastCreatedForce())
is giving me "expected name"
 

Pyromancer3d

New Member
Reaction score
1
emjlr3 said:
lol I just posted one of these :p

And it was very helpful too, until I realized you can only use custom scripts in the Frozen Throne version of WE. Unfortunate for me. I may make another suitable map later for the Frozen Throne to eliminate the leaks, unfortunately for my friends without the expansion, they will have to suffer the leaks for now.
 

JuffoWup

New Member
Reaction score
6
How are u supposed to used Preset variables on lets say Abilitys area of effect if 2 heroes happen to cast same spell at the same time ? Lets say I got variable "Fireball" to determinate certain area where spell does damage, and the region that is preset is used in two different places at the same time.
 

xPheRe

New Member
Reaction score
43
Nice tut but I disagree in one thing
Code:
Unit Group - Pick every unit in (Units owned by (Player 1)) and do (Unit - Kill (Picked unit))
Custom Script: call DestroyGroup([b]GetLastCreatedGroup()[/b])
GetLastCreatedGroup as seen in Blizzard.J, creates a new group cloned from the last one that was created.
So it doesn't remove the group you create on the "Pick every...".
This is the code of the functions from Blizzard.J
Code:
function GetLastCreatedGroupEnum takes nothing returns nothing
    call GroupAddUnit(bj_groupLastCreatedDest, GetEnumUnit())
endfunction

function GetLastCreatedGroup takes nothing returns group
    set bj_groupLastCreatedDest = CreateGroup()
    call ForGroup(bj_lastCreatedGroup, function GetLastCreatedGroupEnum)
    return bj_groupLastCreatedDest
endfunction
It clearly clones the group that was in the global variable bj_lastCreatedGroup and sets bj_groupLastCreatedDest to it.
So the group that leaks is stored in bj_lastCreatedGroup, not in bj_groupLastCreatedDest.
And this last is the one you've destroyed with this trigger.

You must use this actions instead
Code:
Custom script: call DestroyGroup(bj_lastCreatedGroup)
Or store the group in a temp variable
Code:
Set ugTmp = Units owned by (Player 1)
Unit Group - Pick every unit in (ugTmp) and do (Unit - Kill (Picked unit))
Custom script: call DestroyGroup(udg_ugTmp)

About forces, there's no GetLastCreatedForce() function.
You have to store the force in a variable, destroying it later to avoid the leak.
Code:
Set pgTmp = Convert Player 1 To Player Group
...
Custom script: call DestroyForce(udg_pgTmp)

I hope this clarifies even more things about leaks :)
 

phyrex1an

Staff Member and irregular helper
Reaction score
447
Code:
Custom script: call DestroyGroup(bj_lastCreatedGroup)

That has no effect.

bj_lastCreatedGroup is the last set of units created with the GUI create units thing. bj_lastCreatedGroup is only initilized ONCE, after that it is just cleared and reused.

There is only 2 ways to remove the group leak from a Pick Every Unit, one has xPheRe allredy mention (to store the group in a varaible, use, destroy). That is the best way.

The other is to use the hack set bj_wantDestroyGroup = true. This hovever is buggy with pick random N units from group.



~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Overall rating: /\ /\



Link to the other tutorial:
http://www.thehelper.net/forums/showthread.php?t=27219
 
B

Benny

Guest
nice tutorial, both of you..

however, is there a way of measuring how bad your map is leaking besides seeing if its very laggy?
 

phyrex1an

Staff Member and irregular helper
Reaction score
447
You always have the task manager (Ctrl + Alt + Del) where you can se memory usage. If this increasing fast your map probleby has leaks. A small increasment is just ok (more units, replay saved and stuff like that)

And if it takes very long time to close you wc3 after plaing a map (x2 times the normal time) it may be leaks in the map.
 

Rad

...
Reaction score
228
xPheRe and phyrex1an:

I'm not a JASS expert, and xPheRe your thing complicated things more than clerifying them.. :eek:

I think it was Im_On_56k who told me that one, not exactly sure though

PS: Why dont you guys make a good one, that has every type of memory leak and is very easy to use...? BTW xPheRe your post was very complicated, one had 2 groups of different lines, what should I do with those? I use custom script lines, not word for word JASS


emjlr3:

I glanced over tutorials before submitting, I didnt even notice yours... might have been in a back page (I didnt go through every page as I already saw one...) So yea, sorry

EDIT~

@Yoshii - If thats giving you an error, maybe the (lastcreatedforce()) doesnt work for player groups... as I said I'm not a JASS expert so phrex or sphere need to answer that for you ;)

Try using a variable for it... Also Ill update why they are bad
 

phyrex1an

Staff Member and irregular helper
Reaction score
447
Groups: These are fairly easy to remove, so long as they do not use waits as well. It was suggested to only use waits in integer loops by a few people higher than me.

Leak:
Code:
Unit Group - Pick every unit in (Units owned by (Player 1)) and do (Unit - Kill (Picked unit))

Fix 1:
Code:
set UnitGroup = (Units owned by (Player 1))
Unit Group - Pick every unit in UnitGroup and do (Unit - Kill (Picked unit))
Custom Script: call DestroyGroup(udg_UnitGroup)
NOTE: If you replace Group with Force you can do this with Player Groups to, however some player groups are static. Example: (All Players)

Fix 2:
Code:
Custom Script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units owned by (Player 1)) and do (Unit - Kill (Picked unit))
Note: The first fix is better.

Here is the group section rewritten ^^.

btw why should we write a tutorial when we allredy have 2? ^^ We couldn't do better, there isn't many ways to remove leaks...
 

Rad

...
Reaction score
228
Gotta go to school now, ill update later.

Oh and you guys should because A: You know JASS and I dont, B: You know why they dont work, and can explain alot better!
 

xPheRe

New Member
Reaction score
43
Rad said:
(...) BTW xPheRe your post was very complicated, one had 2 groups of different lines, what should I do with those? I use custom script lines, not word for word JASS (...)
I clearly said what the code inside the box is. It's the code of two functions from Blizzard.J
Actually it's the JASS code called whenever you call GetLastCreatedGroup
If you don't want to know about JASS (and I know you don't want) just skip it and don't try to understand.
Rad said:
PS: Why dont you guys make a good one, that has every type of memory leak and is very easy to use...? BTW xPheRe your post was very complicated, one had 2 groups of different lines, what should I do with those? I use custom script lines, not word for word JASS
English isn't my first language (nor my second... it can be called my third) so often my posts can be unclear.
Nobody wants an unclear tutorial.
That's the reason I have written none.
 

Rad

...
Reaction score
228
I clearly said what the code inside the box is. It's the code of two functions from Blizzard.J
Actually it's the JASS code called whenever you call GetLastCreatedGroup
If you don't want to know about JASS (and I know you don't want) just skip it and don't try to understand.

Your confusing me again... :eek:

You english seems good to me, isnt english one of the easiest (as its integrated from other languages)?

EDIT

Pyromancer3d said:
And it was very helpful too, until I realized you can only use custom scripts in the Frozen Throne version of WE. Unfortunate for me. I may make another suitable map later for the Frozen Throne to eliminate the leaks, unfortunately for my friends without the expansion, they will have to suffer the leaks for now.

Why dont you just tell them you buy TFT? I mean come on its $20 MAX. I got the battlechest (Both + strategy guide I lost the next day) for 25 dollars, I think it was 25, might have been 20. That was a year ago...
 
C

Cepheids

Guest
dont understand

- Points: These are the most dangerous when making spells and movement systems with keyboard. Whenever you use the position of an object or a point of a region (Whether it be random or center), and even coordinates, they create a memory leak.

Why isnt there a leak when u do this?

Code:
Set Point = (Center of (Region A))
Unit - Create 1 footman at (Point) for Neutral Passive facing default building degrees
Custom Script: call RemoveLocation(udg_Point)

You are still using (Center of (Region A)). You just created an extra point. Now you have both (Center of (Region A)) and variable Point in memory. You only destoryed the variable Point.

If (Center of (Region A)) does not chalk up memory when you use

Code:
Set Point = (Center of (Region A))

Why would it when you use this?

Code:
Unit - Create 1 footman at (Center of (Region A)) for Neutral passive facing default building degrees

Also, from the rest of the tutorial, wouldnt

Code:
Set Point = (Center of (Region A))

mean a leak due to use of (Region A) too?

Therefore, the code should be as follows right?

Code:
Set (Region) = (Region A)
Set Point = (Center of (Region))
Unit - Create 1 footman at (Point) for Neutral Passive facing default building degrees
Custom Script: call RemoveLocation(udg_Point)
Custom Script: call RemoveRect(udg_Region)

Please tell me where i went wrong.
 

AceHart

Your Friendly Neighborhood Admin
Reaction score
1,494
> Unit - Create 1 footman at (Center of (Region A))

This creates a new point and uses it.
But, once done, the point is lost, hence the leak.

> Set Point = (Center of (Region A))

This will also create a new point.
But, the reference to it will be saved in the variable.
And, upon destruction, this reference, and, therefore, the new point, will be destroyed.
The variable is just fine after that and can be reused for other things.
 
Z

Zpothu

Guest
nice tutorial but....

could you please include a link to download a simple map with the custom script done for me so that maybe i can save and paste the trigger and never have to worry about the complicated stuff in which you speak?
 
I

iNsaNe

Guest
wow nice tutorial, i will need this for my maze map :D

I guess maze maps are basically composed and triggered by variables and custom scripts
 

WuHT

New Member
Reaction score
6
Diggin up the ol' thread.

Really simple Question
For the trigger
Code:
Set Point = (Center of (Region A))
Unit - Create 1 footman at (Point) for Neutral Passive facing default building degrees
Custom Script: call RemoveLocation(udg_Point)

It mentions a "universal variable point"..so would the following still make sense ?

If i wanted to create footmen for two armies... i would use 2 different points to set for both regions ... would this still prevent leaks ?
 
V

vippe

Guest
tmpPlayer

I got a question, i wanna use:
Code:
set tmpPlayer = (Owner of (Triggering unit))
set tmpPlayer2 = (Triggering player)
.
.
.
Custom script: call DestoryPlayer (udg_tmpPlayer)
Custom script: call DestoryPlayer (udg_tmpPlayer2)

...but it dosent work.. tried with DestroyForce aswell but i still get errors...
..anyone know what i do wrong? or dosent thouse to leak anything?
its player variabletypes cuse i cant use player group for thouse two...
please help me :shades:
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top