• 🏆 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!

Things That Leak

Level 11
Joined
Jul 9, 2009
Messages
926
okay I shall search for a new revive system. thanks to watermelon and baassee. +rep :)
 
Level 11
Joined
Jul 9, 2009
Messages
926
but his revival system is in jass, I dont understand jass even if I wanted to :)
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
The code that you just posted is all JASS.

  • Custom script: local timerdialog WINDOW
  • Custom script: local integer HEROWAIT
  • Custom script: local timer OURTIMER
  • Custom script: local unit OURHERO
  • Custom script: set OURHERO = GetDyingUnit()
  • Custom script: set HEROWAIT = ( GetHeroLevel(OURHERO) * 5 )
  • Custom script: set OURTIMER = CreateTimer()
  • Custom script: call StartTimerBJ( OURTIMER, false, ( I2R(HEROWAIT) ))
  • Custom script: call CreateTimerDialogBJ( OURTIMER, GetPlayerName(GetOwningPlayer(OURHERO)) )
  • Custom script: set WINDOW = GetLastCreatedTimerDialogBJ()
  • Custom script: call TimerDialogDisplayForPlayerBJ( true, WINDOW, GetOwningPlayer(OURHERO) )
  • Custom script: call PolledWait( HEROWAIT )
  • Custom script: call ReviveHeroLoc( OURHERO, GetRectCenter(gg_rct_Sentinel_Start), true )
  • Custom script: call PanCameraToTimedLocForPlayer( GetOwningPlayer(OURHERO), GetUnitLoc(OURHERO), 0.60 )
  • Custom script: call DestroyTimerDialog(WINDOW)
 
Level 11
Joined
Jul 9, 2009
Messages
926
I can simply understand that, cause it is separated from each other, but when I try to read it when it is fully converted to jass, I cant seem to understand =.=

anyway, here I made a trigger out of baassee's Revive system.
I cant seem to make the dialog disappear once the hero revives. and is there any leak here ?

  • Test Revive
    • Events
      • Unit - A unit Dies
    • Conditions
      • And - All (Conditions) are true
        • Conditions
          • ((Dying unit) is A Hero) Equal to True
          • Or - Any (Conditions) are true
            • Conditions
              • (Owner of (Dying unit)) Equal to Player 1 (Red)
              • (Owner of (Dying unit)) Equal to Player 2 (Blue)
              • (Owner of (Dying unit)) Equal to Player 3 (Teal)
              • (Owner of (Dying unit)) Equal to Player 4 (Purple)
    • Actions
      • Set TempUnit = (Dying unit)
      • Set TempLoc = (Center of Sentinel Start <gen>)
      • Set TempReal = ((Real((Level of (Dying unit)))) x 5.00)
      • Set Herowait = (Last started timer)
      • Set Revive = (Last created timer window)
      • Countdown Timer - Start Herowait as a One-shot timer that will expire in TempReal seconds
      • Countdown Timer - Create a timer window for Herowait with title (Name of TempUnit)
      • Countdown Timer - Show Revive
      • Wait TempReal seconds
      • Camera - Pan camera for (Owner of TempUnit) to TempLoc over 0.00 seconds
      • Hero - Instantly revive TempUnit at TempLoc, Show revival graphics
      • Custom script: call RemoveLocation(udg_TempLoc)
 
Level 22
Joined
Nov 14, 2008
Messages
3,256
^Berb caught the main point. So did Mag although I didnt wanna advertise and get another warning from Rui :D (It's always you Rui if you see this)

EDIT:

Except that you have a wait (which is really bad), you have to destroy the window after the wait or it will not go away.
 
Level 11
Joined
Jul 9, 2009
Messages
926
oh, I did not know using wait is bad. Is there another solution than using wait ?? And there are no leaks ??
 
I have a question : How can I store a UnitGroup and keeps it without any changes without leaking.

Because I have a trigger like this :
  • Trigger
    • Events
      • Temps - Every X.XX seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in GroupVar and do (Actions)
        • Loop - Actions
        • -------- Actions --------
And so i need to keep all of my units in the Unit Group Variable. But it leaks if i don't modify anything and how can i remove this leak without removing the units from the Unit Group ?
 
Level 3
Joined
Nov 16, 2011
Messages
54
I have a question : How can I store a UnitGroup and keeps it without any changes without leaking.

Because I have a trigger like this :
  • Trigger
    • Events
      • Temps - Every X.XX seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in GroupVar and do (Actions)
        • Loop - Actions
        • -------- Actions --------
And so i need to keep all of my units in the Unit Group Variable. But it leaks if i don't modify anything and how can i remove this leak without removing the units from the Unit Group ?

Once a unit group i saved into variable it's no longer leaking because you can always refer to this variable and destroy the unit group. This mean that you can use this variable everywhere in your triggers without causing additional memory leaks.
 
Level 11
Joined
Jun 21, 2007
Messages
505
Even if you 'add to group' or 'remove from group' a unit (using GroupAddUnit(group,unit) or GroupRemoveUnit(group,unit) native functions) there won't be any leaks. If you just cycle through the unit group in the way which you showed (post #955) there are still no leaks.
You shouldn't worry about leaks, because there are none, even if something is done with that group.

If you want to make it so that units cannot be added or removed from that group (which can only be done with triggers, or when the corpse of the unit has fully decayed after 88 seconds), then you should use an array of units instead of a group. You can fully control how units are added or removed, except that when a unit dies and decays for too long, then it is removed automatically and the group doesn't have that unit any more in it.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
kkots said:
You can fully control how units are added or removed, except that when a unit dies and decays for too long, then it is removed automatically and the group doesn't have that unit any more in it.

No, they are not removed of the group automatically, but you can't enum them (short story), we call them ghost units : units removed of the game but not of the group.
In the case you don't remove all units using GroupClear or GroupRemoveUnit, or just a GroupEnum... function, you still can clean the group periodically, like using the function GroupRefresh of the vJass library GroupUtils (just as an example)

Theorically there will be a performance issue with a group full of many ghost units comparing to the same group without ghost units, but i don't think that will be ever noticeable in any real case, especially in GUI.
 
Level 11
Joined
Jun 21, 2007
Messages
505
No, they are not removed of the group automatically, but you can't enum them (short story), we call them ghost units : units removed of the game but not of the group.
In the case you don't remove all units using GroupClear or GroupRemoveUnit, or just a GroupEnum... function, you still can clean the group periodically, like using the function GroupRefresh of the vJass library GroupUtils (just as an example)

Theorically there will be a performance issue with a group full of many ghost units comparing to the same group without ghost units, but i don't think that will be ever noticeable in any real case, especially in GUI.

Remove the unit from the group as soon as it dies? Will that fix the ghost units problem?
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Or instead of simply remove unit, Kill it before. (easy GUI fix)
Ofc in case an unit can resurect and you don't want to remove it, that wouldn't work.
But seriously, as i've mentioned i don't think you really need to care about that, i just said it for the sake of accuracy.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,454
I think you'd have to be spawning at least a million units over time to notice an issue. Possibly millions, but I haven't got time to test that as my computer won't support more than 1000 created units at a time.

Most lag will be caused by corpse decay and the blood splatter of exploded units. The corpse decay was such a problem for me in WarChasers 2 that I set the decay time to 12 seconds or something.

In a lot of cases you can use dummy recycling or not even need to create extra dummies in the first place (like having one dummy caster for most tasks).
 
Level 10
Joined
Nov 24, 2010
Messages
546
Hello guys, I am new to triggering and removing leaks, here is my question:

  • ManaTideTotem
    • Events
      • Time - Every 3.00 seconds of game time
    • Conditions
      • (Number of units in (Units of type Tidal Totem)) Equal to 1
    • Actions
      • Set HolHin_Mana = (Random real number between 2.00 and 5.00)
      • Unit Group - Pick every unit in (Units within 1000.00 of (Position of HolHin_Totem)) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Unit-type of (Picked unit)) Not equal to Lady Seraspia
              • (Unit-type of (Picked unit)) Not equal to Tidal Totem
            • Then - Actions
              • Unit - Set mana of (Picked unit) to ((Mana of (Picked unit)) + HolHin_Mana)
              • Floating Text - Create floating text that reads ((|c000000ff+ + (String((Integer(HolHin_Mana))))) + mana|r) above (Picked unit) with Z offset 0.00, using font size 8.50, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
              • Floating Text - Change (Last created floating text): Disable permanence
              • Floating Text - Change the lifespan of (Last created floating text) to 1.25 seconds
              • Floating Text - Change the fading age of (Last created floating text) to 1.00 seconds
              • Floating Text - Set the velocity of (Last created floating text) to 85.00 towards 135.00 degrees
            • Else - Actions
Does this leak in group?
 
Yes the conditions leak to. The solution is to use an if/then/else (multiple conditions) and do everything in the actions, so that you can destroy the group.

If there were no "conditions", then everyone would just use the if/then/else (multiple conditions) block. They are not really important.

Or you just should to turn on/off the trigger ^^

It's the best optimisation way, no ?
 
Level 8
Joined
Sep 18, 2011
Messages
195
Rect and Regions

JASS:
    local rect rect_1 = Rect(x-400.,y-400.,x+400.,y+400.)
    local rect rect_2 = RectFromCenterSizeBJ(loc, 400.0, 400.0)
    local region region_1 = CreateRegion()
    RegionAddRect(region_1 , rect_1)
    RegionAddRect(region_1 , rect_2)
    //...1
    RemoveRect(rect_1)
    RemoveRect(rect_2)
    //...2
1. After I added the rects, Does the region need the rects not-destroyed to work?
2. Rect and Regions both leaks?
 
If the region is being used for a Unit-Enter-Region Event, then don't destroy it.
The game doesn't create a copy of this region for the event, it uses the same region you passed in, so destroying the region will render your trigger useless.

As for rects, I'm not very sure, but I believe destroying them should cause the same side-effects.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Since rects are added to regions "by value" and not "by reference", if you don't need them anymore, then you can destroy them.

Rects and regions leak if you don't destroy them when you don't have the need anymore, but that's pretty much like every handles (excepted texttags probably since there is an hardcoded limit of 100 texttags)
There is also the special case with boolexpr created with Filter() and Condition(), never destroy them if you don't know exactly what you're doing.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Units do leak. There is some internal game bug that removing a unit (any means including natural death) does not removal all memory used by a unit. There is no way to avoid this leak next to unit recycling (re-use existing units instead of making more).

IIRC this leak is very minor or there is even no leak at all.
For some simple and precise applications like dummies units, recycling is fine, as it is far more efficient.
For the rest, recycling brings more problems than just create/destroy units.

But for destructable it's significant, can't say how many bytes but that's clearly visible (i tested it with some tree, it could be not the same with other destructable).

For doodads they can't be removed anyway, right ?
 
The unit leak used to be a major problem in patch 1.24, but I think they fixed it when they released 1.25. Maybe they did not fix it completely (I don't remember), but people actually ran into memory limits after playing about fifteen minutes to half an hour into a melee map. That doesn't seem to happen anymore, and I remember running tests a long time ago to test if the memory problem was still as great and found that they weren't.
 
Level 5
Joined
Sep 22, 2012
Messages
90
You don't allocate or deallocate memory yourself. The game allocates memory for objects you create in triggers. The only thing you need to do is destroy the object, so the allocated memory is freed. However you also need to null any local references to destroyed objects because otherwise that specific handle index can't be recycled.
noob here, someone please help. how do i know references from triggers? i've started making some triggers with clearing mem leaks like location with polar offsets and unit groups. here is my map: http://www.hiveworkshop.com/forums/spells-569/8-way-arrowkeys-223047/


please help. I want to learn gui triggers T_T
 
Level 4
Joined
Jan 27, 2008
Messages
72
Hello guys!
Credit to: Wolverabid, PurplePoot, Silvenon, Paskovich

I want to make a list of things that leak and ways to fix them.

Dynamic Unit Groups

This trigger will instantly destroy dynamically generated unit groups.

  • Trigger
    • Events
      • Event
    • Conditions
      • Conditions
    • Actions
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Playable Map Area) and do (Unit - Hide (Picked unit))
Another way to avoid a group leak is to store the group into a variable, and then destroy it manually.

  • Set GroupVar = Pick every unit in (Playable Map Area)
  • Unit Group - Pick every unit in GroupVar and do (Unit - Hide (Picked unit))
  • Custom script: call DestroyGroup(udg_GroupVar)
This is useful if you want to use the group more than once in the trigger.​

Hm, the set bj want destroy group custom script removed the special effect from the group of units.
 
Level 4
Joined
Jan 27, 2008
Messages
72
  • Indignation Visual
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Indignation (Neutral Hostile 1)
    • Actions
      • Set IndignationGroup = (Units within 375.00 of (Position of (Triggering unit)))
      • For each (Integer A) from 1 to 5, do (Actions)
        • Loop - Actions
          • Custom script: set bj_wantDestroyGroup = true
          • Unit Group - Pick every unit in (Random 1 units from IndignationGroup) and do (Special Effect - Create a special effect attached to the overhead of (Random unit from IndignationGroup) using Abilities\Spells\Other\Monsoon\MonsoonBoltTarget.mdl)
          • Special Effect - Destroy (Last created special effect)
      • Custom script: call DestroyGroup (udg_IndignationGroup)
It might be because of the loop? Or I placed it in the wrong place.

Oh wait, I just realized that it might be redundant, lol.
 

Ralle

Owner
Level 77
Joined
Oct 6, 2004
Messages
10,096
You are picking a random unit from the group 5 times and creating a special effect which you immediately destroy. This does not work.
You need to insert waits, but when doing that, it will not be MUI, so you need local variables, which are not accessible through GUI.
The way you would do it would be to have an array containing each special effect after you create them, then after x seconds, you destroy the special effects.
 
Level 4
Joined
Jan 27, 2008
Messages
72
The special effect works just fine without the first custom script in the trigger.

I just thought that the trigger leaked without it, but it doesn't, correct?
 
  • Indignation Visual
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Indignation (Neutral Hostile 1)
    • Actions
      • Set TempLoc = (Position of (Triggering unit))
      • Set IndignationGroup = (Units within 375.00 of TempLoc)
      • For each (Integer A) from 1 to 5, do (Actions)
        • Loop - Actions
          • Special Effect - Create a special effect attached to the overhead of (Random unit from IndignationGroup) using Abilities\Spells\Other\Monsoon\MonsoonBoltTarget.mdl)
          • Special Effect - Destroy (Last created special effect)
      • Custom script: call DestroyGroup(udg_IndignationGroup)
      • Custom script: call RemoveLocation(udg_TempLoc)
No need of group.

If you want that an effect can't be created twice on the same unit :

  • Indignation Visual
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Indignation (Neutral Hostile 1)
    • Actions
      • Set TempLoc = (Position of (Triggering unit))
      • Set IndignationGroup = (Units within 375.00 of TempLoc)
      • For each (Integer A) from 1 to 5, do (Actions)
        • Loop - Actions
          • Set TempUnit = (Random unit from IndignationGroup)
          • Special Effect - Create a special effect attached to the overhead of TempUnit using Abilities\Spells\Other\Monsoon\MonsoonBoltTarget.mdl)
          • Special Effect - Destroy (Last created special effect)
          • Unit Group - Remove TempUnit from IndignationGroup
      • Custom script: call DestroyGroup(udg_IndignationGroup)
      • Custom script: call RemoveLocation(udg_TempLoc)
 
Top