1. Find your way through the deepest dungeon in the 18th Mini Mapping Contest Poll.
    Dismiss Notice
  2. A brave new world lies beyond the seven seas. Join the 34th Modeling Contest today!
    Dismiss Notice
  3. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
Hive 3 Remoosed BETA - NOW LIVE. Go check it out at BETA Hive Workshop! Post your feedback in this new forum BETA Feedback.
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Leaking but don't know why

Discussion in 'Triggers & Scripts' started by D4RK_G4ND4LF, Apr 7, 2010.

  1. D4RK_G4ND4LF

    D4RK_G4ND4LF

    Joined:
    Feb 4, 2009
    Messages:
    1,196
    Resources:
    20
    Models:
    3
    Spells:
    15
    Tutorials:
    2
    Resources:
    20
    Can't find the leak (probably something new)

    Code (vJASS):
    function EnumStandardFilter takes nothing returns boolean
        set udg_ue = GetFilterUnit()
        return not(IsUnitType(udg_ue,UNIT_TYPE_MECHANICAL)or IsUnitType(udg_ue,UNIT_TYPE_STRUCTURE)or IsUnitType(udg_ue,UNIT_TYPE_DEAD)or IsUnitType(udg_ue,UNIT_TYPE_FLYING)or IsUnitType(udg_ue,UNIT_TYPE_MAGIC_IMMUNE)) and IsUnitEnemy(udg_ue,udg_p)
    endfunction

    function GroupEnumStandard takes group g, unit u, real x, real y, real r returns nothing
        local boolexpr be = Condition(function EnumStandardFilter)
        set udg_p = GetOwningPlayer(u)
        call GroupEnumUnitsInRange(g, x, y, r, be)
        set be = null
    endfunction


    • Execute
      • Events
        • Player - Player 1 (Red) skips a cinematic sequence
      • Conditions
      • Actions
        • Set i2 = 0
        • Custom script: loop
        • Custom script: exitwhen udg_i2 > 2000
        • Custom script: call GroupEnumStandard(udg_g, udg_u, 0, 0, 500)
        • Set i2 = (i2 + 1)
        • Custom script: endloop
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • i Less than 1000
          • Then - Actions
            • Set i = (i + 1)
            • Trigger - Run (This trigger) (ignoring conditions)
          • Else - Actions
            • Game - Display to (All players) the text: rdy


    every time I press "Esc" WC3 allocates one more MB of RAM

    edit: the trigger really should run 2 million times else I can't measure the leak cause it is small

    please help me find the leak

    Note:
    Code (vJASS):
    call DestroyBoolExpr(be)
    made this trigger leak like 10 MB per second

    edit2: similar ammount of leak:
    Code (vJASS):
    set g = CreateGroup()
    call GroupEnumUnitsInRange(g, x, y, r, be)
    call DestroyGroup(g)
    set g = null

    (of cause this destroys the group so I can't use it any longer but it was just to test that it leaks)
     
    Last edited: Apr 7, 2010
  2. Pharaoh_

    Pharaoh_

    Joined:
    Nov 6, 2008
    Messages:
    8,128
    Resources:
    11
    Icons:
    3
    Skins:
    1
    Spells:
    6
    Tutorials:
    1
    Resources:
    11
    Try lowering the 2000 integer value.
    • Custom script: exitwhen udg_i2 > 2000


    What is more:
    • Trigger - Run (This trigger) (ignoring conditions)

    Remove that action, seriously.
     
  3. D4RK_G4ND4LF

    D4RK_G4ND4LF

    Joined:
    Feb 4, 2009
    Messages:
    1,196
    Resources:
    20
    Models:
    3
    Spells:
    15
    Tutorials:
    2
    Resources:
    20
    this trigger is to test if it leaks
    my mistake
    should have said that
    but I posted it cause I wasn't sure if I might used something in the execute function which leaks
     
  4. ZiggyMcjoney

    ZiggyMcjoney

    Joined:
    May 4, 2008
    Messages:
    109
    Resources:
    1
    Maps:
    1
    Resources:
    1
    Wouldn't it be the GroupEnumUnitsInRange function that is leaking? You haven't destroyed the group there, so it's leaking a unit group.

    You need to set all the values to a local group variable and then destroy it at the end of the function.
     
  5. D4RK_G4ND4LF

    D4RK_G4ND4LF

    Joined:
    Feb 4, 2009
    Messages:
    1,196
    Resources:
    20
    Models:
    3
    Spells:
    15
    Tutorials:
    2
    Resources:
    20
    nope

    that's for the GUI function only cause it CREATES a group
    GroupEnumUnitsInRange only works if the group was created already and adds the units to the group instead

    I also made a test with destroying the group
    it leaked a lot cause it doesn't set free all the memory
     
  6. Dr Super Good

    Dr Super Good

    Spell Reviewer

    Joined:
    Jan 18, 2005
    Messages:
    26,190
    Resources:
    3
    Maps:
    1
    Spells:
    2
    Resources:
    3
    Make sure that the group is clean by clearing it every so often.

    I can also advise debugging the game and seing where the leak is occuring. It might be a once off leak as it allocates some memory before starting to recycle it.
     
  7. DevilDuke1995

    DevilDuke1995

    Joined:
    Nov 6, 2009
    Messages:
    246
    Resources:
    0
    Resources:
    0
    How the hell do you know how much it leaks?

    EDIT: make the boolexpr global instead of calling the Condition function all the time.
    EDIT2: Blizzard has made DestroyGroup and DestroyTimer really crappy thatz why there are recycling systems.
     
  8. D4RK_G4ND4LF

    D4RK_G4ND4LF

    Joined:
    Feb 4, 2009
    Messages:
    1,196
    Resources:
    20
    Models:
    3
    Spells:
    15
    Tutorials:
    2
    Resources:
    20
    Code (vJASS):
    call GroupClear(g)

    does not make a difference but was worth a shot

    it's not a game
    just a map with these two triggers in it

    task manager
    not accurate but you can tell the difference between no leak and leak

    you can't make global boolexpr variables with GUI/normal JASS afaik

    @all people who want me to use JNGP (there always are some who will write something about it and this is just to make the stop spamming me to death)
    NO! I WILL IGNORE ANYTHING REGARDING THAT!
    (it has nothing to do with the topic anyway)
     
  9. DevilDuke1995

    DevilDuke1995

    Joined:
    Nov 6, 2009
    Messages:
    246
    Resources:
    0
    Resources:
    0
    Yeah no boolexpr type at VE... my bad

    Link to task manager??? plz??

    JNGP IS THE ONLY SOLUTION! YOU CANT LIVE WITHOUT IT! IF YOU DONT USE YOU MUST DIE INSTANTLY CAUSE YOU ARE HUMANITY'S SHAME!

    hope u fell for that... (this means im kidding)

    EDIT2: Task Manager = Ctrl + Alt + Del?
    EDIT3: Task Manager translation in my language sucks
     
  10. D4RK_G4ND4LF

    D4RK_G4ND4LF

    Joined:
    Feb 4, 2009
    Messages:
    1,196
    Resources:
    20
    Models:
    3
    Spells:
    15
    Tutorials:
    2
    Resources:
    20
    I thought it would only be my country which had the most ugliest language ever :ugly:

    just figured out that one can save boolexprs in hashtables
    by doing this I don't require the wrapper function anymore :D
    and I don't care about this minor leak any longer since I calculated that group enumerations run 33.333 times per second max usually
    (so I will need 20 years to fill the ram with 4 GB of trash until the game breaks)

    however if someone is going to figure out why I still would like to know :grin:
     
  11. PurgeandFire

    PurgeandFire

    Code Moderator

    Joined:
    Nov 11, 2006
    Messages:
    7,430
    Resources:
    18
    Icons:
    1
    Spells:
    4
    Tutorials:
    9
    JASS:
    4
    Resources:
    18
    I think enumerations auto-clear. Then again, I think shadow references take up a bit of RAM, so I guess there is no harm in it. =P

    Anyway:
    Code (vJASS):
    function EnumStandardFilter takes nothing returns boolean
        set udg_ue = GetFilterUnit()
        return not(IsUnitType(udg_ue,UNIT_TYPE_MECHANICAL)or IsUnitType(udg_ue,UNIT_TYPE_STRUCTURE)or IsUnitType(udg_ue,UNIT_TYPE_DEAD)or IsUnitType(udg_ue,UNIT_TYPE_FLYING)or IsUnitType(udg_ue,UNIT_TYPE_MAGIC_IMMUNE)) and IsUnitEnemy(udg_ue,udg_p)
    endfunction

    function GroupEnumStandard takes group g, unit u, real x, real y, real r returns nothing
        local boolexpr be = Condition(function EnumStandardFilter)
        set udg_p = GetOwningPlayer(u)
        call GroupEnumUnitsInRange(g, x, y, r, be)
        set be = null
    endfunction


    Just use the "Condition(function EnumStandardFilter)" directly. But I am not sure if that would fix the problem. Conditions auto-recycle so I don't understand why it'd cause that. Did you test this in a blank map without anything else?

    For this:
    Code (vJASS):
    set g = CreateGroup()
    call GroupEnumUnitsInRange(g, x, y, r, be)
    call DestroyGroup(g)
    set g = null


    Destroying groups leak a tiny bit of RAM. That's why people recycle groups. =D (Basically, use a global group and just reuse it)

    Otherwise, I don't know what causes it. Maybe enumerations take up a little bit of RAM, I dunno. =P It is an interesting find though, but you might want to test it more thoroughly with a null boolexpr or a "return false" dummy condtion just to be sure.
     
  12. D4RK_G4ND4LF

    D4RK_G4ND4LF

    Joined:
    Feb 4, 2009
    Messages:
    1,196
    Resources:
    20
    Models:
    3
    Spells:
    15
    Tutorials:
    2
    Resources:
    20
    d'oh! great idea xD

    made some further tests
    I changed my trigger to run 50 times every 0.01 sec and it turns out that none of the methods mentioned below leaks (not even the one with null)
    however while testing with the old trigger I noticed that the ram usage went up to +10-20 mb and dropped back again after a few seconds (probably the recycling took place during that time)

    wrapper function
    19 fps
    load from hashtable
    21 fps
    direct conversion
    21 fps
    null
    65 fps (max)

    I also tested the null function with ForGroup
    it is A LOT faster
    but as soon as I added the conditions to the ForGroup actions it was slower
    so one shouldn't use filters if the possibility of units being picked while casting stuff is low

    will test this a little more anyway cause it is too weird to be true

    edit:
    made another test
    it is 5-10 times faster to enumerate all units without filter and then checking them in the ForGroup function instead of the usual way

    I can't really believe this so I'd like someone else to test it

    1.
    usual enumeration with filter and ForGroup

    2.
    enumeration with null-filter and ForGroup with "if picked unit is valid do stuff"

    both with a few valid and invalid units

    edit2:
    made another test again which proved the opposite o_O
    however it might be possible that null-filters are slower if the condition list is short or if there aren't many targets on the map anyway (e.g. for passive immolation) but since I can make tests with different results I'll stop them now and let the big guys do them

    the only things I am sure about now:
    -it is pointless to load boolexpressions from hashtables
    -null-filter enumerations are fucking fast
    -nothing leaks unless you destroy it
    -recycling takes some time (which made me think it would leak)

    edit3:
    made a long-term test and ran a null-filter enumeration 500 million times
    after that I had +0.5 MB RAM but it took half an hour so it could be just wc3 itself
    however
    I will use null-filter enums for GUI now cause I won't need any custom functions (only one line of custom script) and is it much faster and leak-free
     
    Last edited: Apr 8, 2010
  13. ikillforeyou

    ikillforeyou

    Joined:
    Jun 10, 2008
    Messages:
    1,340
    Resources:
    33
    Models:
    22
    Icons:
    9
    Packs:
    1
    Tutorials:
    1
    Resources:
    33
    gasp
    maybe it's because GroupEnumSingle isn't using
    Code (vJASS):
     call DestroyBoolExpr(be)


    =o
     
  14. PurgeandFire

    PurgeandFire

    Code Moderator

    Joined:
    Nov 11, 2006
    Messages:
    7,430
    Resources:
    18
    Icons:
    1
    Spells:
    4
    Tutorials:
    9
    JASS:
    4
    Resources:
    18
    @Dark: Cool. =D Now I feel like I should get my benchmarks out and start testing stuff. =P

    Conditions (boolexprs/filterfuncs in general) auto-recycle so that it reuses it each time, rather than generating a new boolexpr each time. (It generates it once the first time, and then it reuses that over and over rather than creating a new boolexpr) That's why destroying isn't needed. ;)
     
  15. Kanadaj

    Kanadaj

    Joined:
    Oct 18, 2008
    Messages:
    1,584
    Resources:
    2
    Icons:
    2
    Resources:
    2
    Just a quick question: 99% of it is custom script. Why don't you just convert it? :D