• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Things That Leak

What I mean is a single variable for every handle, best example could be a location.
Now you assign a variable to it and the counter increases by 1. If you set the variable to a new value, the counter of the location will decrease by 1. If the counter is 0 destroy the location automaticly, assuming that locals are cleared automaticly if the function ends...
Wouldn't that be quite simple for most handles?
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
No, he says that every time you "use" set with a pointer(to an object) variable, increase/decrease the pointer counter to that object and if it is 0 than destroy the object.
That will put some stress on the cpu but it will be constant and not unexpected.

P.s. It will not be much stress.
Blizzard already have a reference counter( of some sort) for all the objects. But they do not check if it reaches 0. So if that counter were to be used, there will be no extra lag.

Only problem with such a "garbage collector" would be with things you want to be permanent.
 
No (@Eleandor, spiwn is right^^), I'm talking about a wannabe garbage collector which allocates a single integer variable for each handle... whenever you create a location, an integer is allocated that counts how many variables point on the location (game cache should be kept in mind too). If that value is 0, there is NO way you could do anything with that location and it could get automaticly removed. Same with groups, timers (if they're not running), boolexpressions and so on. Some stuff like special effects need more checks, so effects could be removed after (birth+stand+death animation) seconds.

EDIT: yay^^ heard of that reference counter too, but wasn't sure anymore
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
But then you're moving the problem...

You'll constantly have to null your pointer when you're no longer using the pointer variable so the object reference counter doesn't get bugged. So in order to make sure your object will be removed when you have no more pointers pointing to it, you must always null them. You might as well just write "RemoveLocation" instead of "set lp = null".

Even though you could automate the nulling process whenever you set your pointer to a new value, you'll still have to null them manually when you're using global variables. So basically you're doing more work than you would have to if you just manually run the deconstructors.

It would also bug with the current handlevar system (storing handles cast as strings in gamecache) because you basically create a local variable (counter = 1), then store the handle as an integer in the game cache and leave the function (counter becomes 0, object will be destroyed). When you then load your variable from the game cache, it's gone.

Sounds a lot simpler to me to simply do it manually. More efficient and more reliable if you know what you're doing.
 
(game cache should be kept in mind too).

Thats what I already wrote, but nevermind :p
Since there is no "variable gets un/assigned" event we cant do that, but blizzard could. It was just an idea of a very simple, and very fast garbage collector. The variable counter is already running in warcraft so this wouldn't change anything. They only have to add the check for the variable being 0, don't think that this would stress a computer to much :/

So what I want from blizzard:
a) Automatic nulling if you have no reference to the pointer (function runs out)
b) Check condition for the variable being 0
c) Reminding the game cache

But we'll never get this :(

Oh, and:
So in order to make sure your object will be removed when you have no more pointers pointing to it, you must always null them. You might as well just write "RemoveLocation" instead of "set lp = null".
We're already nulling locals, no difference :p but I don't event want to null them^^
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
Cr*p, I knew I was forgetting something.

The only thing I desire from any kind of garbage collector is nulling local variables.

Storing handles in gamecache is messy. I prefer using structs(structs just have an already made index allocator) with anything I might need in them, than store the struct index, that way the reference counter to the object will still be >0 and I will have a way of accessing the object after time.
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
Each time a handle variable is changed, you need to:

- Check if there was a previous object stored already
- If true, decrease the counter of the previous object
- Check if the counter of the previous object is 0, remove the object if true
- Increase the counter of the new object

Then you're also ignoring the complexity of the objects behind the pointer:

For groups, you have to:
- Check if there was a previous object stored already
- If true, decrease the counter of the previous object
- Check if the counter of the previous object is 0. If true, decrease the counter of all units inside the group, then remove the group
- Increase the counter of the new object

Effects attached to a unit probably contain a pointer to the unit too. Upon allocation, you also need to increase the counter and upon de-allocation you need to decrease it again and check if there's still any reference to the unit.

You should also know that there are probably tons of handles being manipulated every second... When performance becomes as important as it is in games, you want to avoid 2 checks and 2 counter increases (and potentially more) each time you change a simple pointer...

I don't know... It might be a solution but it might also be too expensive for large applications...
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
So it gets removed from eventual unit groups which contained it?
It doesn't get "removed" from the unit group, the unit group will simply contain a null value instead of a unit. Don't think this should be a problem.

Oh, and another question I forgot to ask. Which leaks are the most memory demanding? On which is better to keep an eye to? Maybe a ladder would be fine :p

All of em :p

Well, it's pretty useless to say which leak is "worse"...
A location leak isn't bad at all, it probably uses the least memory from all leaks in warcraft 3. The thing is: locations are typically used a LOT in gui (especially periodic spawn triggers and spells), and a LOT of small leaks are still worse than 1 big leak.

In GUI you will usually be using locations, groups, forces and effects. So it's these leaks that you have to pay attention to. But other leaks still count too...
 
Level 13
Joined
May 11, 2008
Messages
1,198
so in other words you can't have too many units on the screen and if you kill a unit or remove a unit either way it will be removing the leak but in killing it you force the game to auto clean the leak but if you remove it then you clean the leak yourself.

right?
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
So what will the Number of units in unit group return after the unit has decayed? Still the same value or it same value minus 1?

Well, I thought that special effect leak consumes more memory as location (basically only 2 reals)

It counts only the units different than null, so it will return the "same value minus 1".

Yes, special effects consume more memory.
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
so in other words you can't have too many units on the screen and if you kill a unit or remove a unit either way it will be removing the leak but in killing it you force the game to auto clean the leak but if you remove it then you clean the leak yourself.

right?

Removing it manually is similar to removing a location: you remove it from the game.
Killing a unit will make the game decay it (if it decays, heroes don't) and the game automatically detects when a unit is decayed so it can be removed.

You can, theoretically, have "as many" units as you want, but the warcraft 3 engine will start lagging after a certain limit is hit because of other reasons.
 
Level 20
Joined
Oct 21, 2006
Messages
3,230
I dont understand what you mean.


example:

event - something
condition - none
action - add triggering player to group seppo

event - every 10 seconds of the game time
condition - none
action - pick all players in seppo
OR
action - set variable playersgroup1=seppo
action - pick all players in playergroup1
action - call removeudg_playergroup1
 
Picking players in a group doesn't leak!
Creating a player group "leaks". You can't even say a group leaks. A leak is an object in the memory without a reference on it, so you can't use it anymore. You can use a player group a thousand times without increasing the memory used by wc3. But if you use stuff like "pick all players MATCHING" wc3 creates a new group and that leaks :/
Btw: (All players) doesn't leak, it is a global group that's created on mapinit.
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
Expressions like "units within 512 of a certain location" automatically create a new unit group. Therefor, whenever you use "units within 512 of a certain location" a new unit group is created again and again and never removed and thus leaks.

In your example, you're never creating any player groups (forces), you're only adding players to the player group and thus you don't leak any player groups.
 
Set point1 = something
Move unit to something
Move camera to something
Destroy something

OR

Set point1 = something
Move unit to something
Destroy something
---
Set point1 = something
Move camera to something
Destroy something

:s
First one works fine. It doesn't matter how many times you use the variable, it will not leak as long as you destroy it.

EDIT: Make sure you're destroying "point1" - not this "something".
 
Level 5
Joined
Oct 18, 2007
Messages
139
I could use some help on a trigger x-x. Been screwing with it for a while now and I can't stop it from leaking. Help would be appreciated.

  • StarBusterSet
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • ((Ability being cast) Equal to Divine Buster (A)) or ((Ability being cast) Equal to Starlight Breaker )
    • Actions
      • Trigger - Turn off (This trigger)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • (Owner of (Casting unit)) Equal to Player 2 (Blue)
              • (Owner of (Casting unit)) Equal to Player 3 (Teal)
              • (Owner of (Casting unit)) Equal to Player 4 (Purple)
              • (Owner of (Casting unit)) Equal to Player 5 (Yellow)
              • (Owner of (Casting unit)) Equal to Player 6 (Orange)
        • Then - Actions
          • Player Group - Add Player 7 (Green) to StarlightPlayerGroup
          • Player Group - Add Player 8 (Pink) to StarlightPlayerGroup
          • Player Group - Add Player 9 (Gray) to StarlightPlayerGroup
          • Player Group - Add Player 10 (Light Blue) to StarlightPlayerGroup
          • Player Group - Add Player 11 (Dark Green) to StarlightPlayerGroup
          • Player Group - Add Player 12 (Brown) to StarlightPlayerGroup
          • Player Group - Add Neutral Hostile to StarlightPlayerGroup
        • Else - Actions
          • Player Group - Add Player 1 (Red) to StarlightPlayerGroup
          • Player Group - Add Player 2 (Blue) to StarlightPlayerGroup
          • Player Group - Add Player 3 (Teal) to StarlightPlayerGroup
          • Player Group - Add Player 4 (Purple) to StarlightPlayerGroup
          • Player Group - Add Player 5 (Yellow) to StarlightPlayerGroup
          • Player Group - Add Player 6 (Orange) to StarlightPlayerGroup
          • Player Group - Add Neutral Hostile to StarlightPlayerGroup
  • Divine Buster New
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Divine Buster (A)
    • Actions
      • Set NanoPoint[2] = (Position of (Casting unit))
      • Set NanoVariables[0] = (Casting unit)
      • Set StarlightCaster = (Casting unit)
      • Unit - Create 1 Divine Buster Dummy for (Owner of NanoVariables[0]) at NanoPoint[2] facing (Target point of ability being cast)
      • Set NanoVariables[2] = (Last created unit)
      • Animation - Play (Triggering unit)'s spell animation
      • Trigger - Turn on Divine Buster Movement <gen>
      • Custom script: call RemoveLocation(udg_NanoPoint[2])
  • Divine Buster Movement
    • Events
      • Time - Every 0.04 seconds of game time
    • Conditions
    • Actions
      • Set DivineDistance = (DivineDistance + 1)
      • Set NanoPoint[3] = (Position of NanoVariables[2])
      • Unit - Move NanoVariables[2] instantly to (NanoPoint[3] offset by 60.00 towards (Facing of NanoVariables[2]) degrees)
      • Unit - Create 1 Divine Buster Dummy for (Owner of NanoVariables[0]) at NanoPoint[3] facing Default building facing (270.0) degrees
      • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
      • Unit Group - To NanohaGroup2 add units near NanoPoint[3] in a range of 300.00 matching (((Owner of (Matching unit)) is in StarlightPlayerGroup) Equal to True)
      • Unit Group - Pick every unit in NanohaGroup2 and do (Actions)
        • Loop - Actions
          • Unit - Cause StarlightCaster to damage (Picked unit), dealing ((0.25 x (Real((Level of Divine Buster (A) for StarlightCaster)))) x (Real((Intelligence of StarlightCaster (Include bonuses))))) damage of attack type Spells and damage type Universal
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • DivineDistance Greater than or equal to 20
        • Then - Actions
          • Unit - Remove NanoVariables[2] from the game
          • Set DivineDistance = 0
          • Unit Group - Pick every unit in NanohaGroup2 and do (Unit Group - Remove (Matching unit) from NanohaGroup2)
          • Custom script: call RemoveLocation(udg_NanoPoint[3])
          • Trigger - Turn off (This trigger)
        • Else - Actions
      • Custom script: call RemoveLocation(udg_NanoPoint[3])
      • Unit Group - Pick every unit in NanohaGroup2 and do (Unit Group - Remove (Matching unit) from NanohaGroup2)
 
Level 13
Joined
May 11, 2008
Messages
1,198
a few questions for you, Rvsoldier...first of all why don't you have (Owner of (Casting unit)) Equal to Player 1 (Red) in those Any conditions?
secondly...oh before i get to the second part why are you turning off the trigger before you have done any other actions? anyway, secondly why don't you just use all enemies of player (triggering player/owner of triggering unit/etc) ? i think that would work, be simple, and leakless. thirdly...oh screw it i forgot what the third question was.

if they don't decay, they're also removed unless they "can raise".

does that mean that ground units that don't raise and don't decay are removed also? or were you only referring to flying units?
 
Level 5
Joined
Oct 18, 2007
Messages
139
a few questions for you, Rvsoldier...first of all why don't you have (Owner of (Casting unit)) Equal to Player 1 (Red) in those Any conditions?
secondly...oh before i get to the second part why are you turning off the trigger before you have done any other actions? anyway, secondly why don't you just use all enemies of player (triggering player/owner of triggering unit/etc) ? i think that would work, be simple, and leakless. thirdly...oh screw it i forgot what the third question was.

1. Then only player one would be able to use it. Using owner of casting unit any color can do it.

1.5. That very first trigger just sets up the targets for the third so it doesn't have to redo it every time the spell is cast. You can shut off the trigger early on in it and the other actions will work, and it prevents it from running twice when it's only meant to run once.

2. Pretty sure enemies don't include neutrals, doing that would screw up the targeting.
 
Level 13
Joined
May 11, 2008
Messages
1,198
what are you talking about? i'm saying that player one CANNOT use it because you didn't add that to the list. you said you don't want only player one to be able to use it, i didn't say change the conditions, i said put that condition in there, in other words add it.

unless you are leaving out some of the trigger that very first trigger does absolutely nothing because all it does is turn itself off. i guess you must be turning it on or running it with another trigger but i'm not sure how it's going to do anything when it turns itself off.

and neutral hostile is an enemy. you might check with someone else but i think those are included in the all enemies of player 1. i know all allies of player 1 works great because it doesn't select players that aren't users or computers so i haven't tried doing enemies of player 1 to make it include neutral hostile so maybe it doesn't but if i had to guess if it did, i would say it does.

edit: ok i read over your post again and it seems you're telling me that it doesn't matter where you put the actions, but i find that unlikely. at the least you are telling me that the action turn off this trigger doesn't occur until the trigger is done. i find that hard to believe.
 
Level 5
Joined
Oct 18, 2007
Messages
139
It shuts off the trigger immediately, just because it's shut off though, doesn't mean it won't complete the rest of its actions. Try putting the shutoff action at the beginning of a trigger that spawns a unit in the center of the map, it'll still work, but only once. I put turn offs like that at the very start of a trigger, to ensure it won't run twice under any circumstance.

Player 1 and 7 (Red/Green) are computers, so they don't need to be included. Now I understand what you mean, sorry I left that out.

That aside, any idea why it would leak?
 
Level 13
Joined
May 11, 2008
Messages
1,198
oh yeah...the third question...what are you using that StarlightPlayerGroup for?
ah, nevermind i see it...
ok i take it the trigger is tested and works and you are looking for leakage?
cuz i'm still trying to figure out if it works lol...
the part where you are matching the units with owner of matching unit...does that work? hmm...

anyway, confusion aside...i'm pretty sure that your remove location and remove unit from group actions shouldn't be in the if then action AND after that. i think you need to take those out of there.
i say this because you're going to get to those actions after the if then action so you don't need them in the if then action and i think that doing it twice is a problem.

sorry i can't be of any more help than this...i'm more of a learner than a teacher when it comes to programming, heh.
 
Level 5
Joined
Oct 18, 2007
Messages
139
No problem, at least you tried and didn't flame or anything, I appreciate that.

And yes, the spell works. My solution to stats based line damage that hits multiple times xD. As for the remove action being there twice, yes I believe you're right about that. I'll try it.
 
Level 8
Joined
Sep 24, 2007
Messages
300
  • Unit - Change ownership of Airfield 0078 <gen> to (Owner of (TRiggering unit)) and Change color
What to do in this case? Storing a player (SomePlayer=Owner of triggering unit)->Action: ...to SomePlayer, or storing unit (SomeUnit=triggering unit-> action: ...to (Owner of SomeUnit)) or none?
 
Level 8
Joined
Sep 24, 2007
Messages
300
ok, if those actions below have no leaks, I got the leak problem, other way not yet. :)

  • Then - Actions
    • Set SelectionLoc[(Player number of (Owner of (Attacked unit)))] = (Position of (Attacked unit))
    • Special Effect - Create a special effect at ShootingLoc[(Player number of (Owner of (Attacked unit)))] using Environment\LargeBuildingFire\LargeBuildingFire1.mdl
    • Special Effect - Destroy (Last created special effect)
    • Custom script: call RemoveLocation(udg_ShootingLoc[(Player number of (Owner of (Attacked unit)))])

edit: leak checker reports me a leak here, what shall I do?

  • Else - Actions
    • Set BankGroup = (Player group((Owner of (Casting unit))))
    • Game - Display to BankGroup for 3.00 seconds the text: You don't have enou...
    • Custom script: call DestroyForce(udg_BankGroup)
 
Last edited:
Level 12
Joined
Apr 27, 2008
Messages
1,228
  • Then - Actions
    • Set SelectionLoc[(Player number of (Owner of (Attacked unit)))] = (Position of (Attacked unit))
    • Special Effect - Create a special effect at ShootingLoc[(Player number of (Owner of (Attacked unit)))] using Environment\LargeBuildingFire\LargeBuildingFire1.mdl
    • Special Effect - Destroy (Last created special effect)
    • Custom script: call RemoveLocation(udg_ShootingLoc[(Player number of (Owner of (Attacked unit)))])

That does not leak.
Advice: There is no need to use arrayed variables here, as the object does not have to exist for more than a single trigger execution withouth waits. So you could:
  • Then - Actions
    • Set temp_location = (Position of (Attacked unit))
    • Special Effect - Create a special effect at ShootingLoc[(Player number of (Owner of (Attacked unit)))] using Environment\LargeBuildingFire\LargeBuildingFire1.mdl
    • Special Effect - Destroy (Last created special effect)
    • Custom script: call RemoveLocation(udgtemp_location)
It wont improve performance, put will keep simple triggers ... well ... simple.

P.s. Try using compleate sentances in your posts. And try to express yourself in a way that anyone could understand you. Because franky I couldn't ;)
 
Level 13
Joined
May 11, 2008
Messages
1,198
Anyone got any advice for me x-x?

your trigger looks like you put a lot of effort into it...but i don't really understand complicated gui.

that's only one reason why i've begun to learn jass.

and now i'm experiencing awesome results in trying to fix problems large and small by recoding my triggers in vjass.

if you haven't started learning jass already, i recommend it. and let me link you to this super awesome tutorial that really helped me a lot with my jass programming. [Tutorial] GUI -> vJASS - The Helper Forums

anyway my guess is that if you write your code in vjass it will be easy to find out what is wrong with the trigger.
 
Level 11
Joined
Feb 14, 2009
Messages
884
  • Region 1
    • Events
      • Unit - A unit enters Down Left One <gen>
    • Conditions
      • (Owner of (Triggering unit)) Equal to Player 6 (Orange)
    • Actions
      • Unit - Order (Triggering unit) to Move To (Center of Down Left Two <gen>)
I wrote this trigger for my TD map. Does it leak? Diablo-dk mentions that moving a unit leaks, but what about ordering it to move?
 
Level 6
Joined
Jun 20, 2005
Messages
108
on some tutorials I've read that to get rid of location leaks, you have to set the var to null:
JASS:
set udg_loc = null

but on others, they use the remove location:
JASS:
call RemoveLocation(udg_loc)

and on other, they use both:
JASS:
set udg_loc = null
call RemoveLocation(udg_loc)

so, which one is right (and why)?
 
Top