• 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.

[Solved] Periodic Unit Group Selection and Unit Life/Mana Adjustment Leaks

Status
Not open for further replies.
Level 3
Joined
Sep 10, 2012
Messages
39
I am attempting to create a system that takes over life/mana regeneration, so that I can easily manipulate it. Simple enough in function, but I'm unable plug the leaks.

Here's the code:

JASS:
function Regenerate takes nothing returns nothing

    local unit RegenUnit = GetEnumUnit()
    //local integer RegenHandleID = GetHandleId(RegenUnit)

    call SetUnitLifeBJ( RegenUnit, ( GetUnitStateSwap(UNIT_STATE_LIFE, RegenUnit) + LoadReal(udg_HashTable_Attributes, GetHandleId(RegenUnit), 70 ) ))
   
   // set RegenHandleID = null
    set RegenUnit = null

   
endfunction

function Trig_Regeneration_Actions takes nothing returns nothing

    local group UnitsInMap = GetUnitsInRectAll(GetPlayableMapRect())
    call ForGroup(UnitsInMap, function Regenerate)
    call DestroyGroup(UnitsInMap)
    set UnitsInMap = null
   
endfunction

//===========================================================================
function InitTrig_Regeneraton takes nothing returns nothing
    set gg_trg_Regeneraton = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Regeneraton, 1.00 )
    call TriggerAddAction( gg_trg_Regeneraton, function Trig_Regeneration_Actions )
endfunction


the RegenHandleID, and the attempted annulment, were my attempts at closing what I can only guess is a leak of integer values, although I have not read of them.

I've read two different memory leak tutorials and done my best to apply the information therein. But it should be noted that I am quite new to JASS/vJASS, so I am still not aware of all aspects of memory leaks, and all the things that cause them.

Any assistance provided in this is greatly appreciated.
 
There are some primitive data types that do not leak:
JASS:
integer
real
boolean
code
string

you don't have to "null" them or anything else.

____

If you want to optimize the code you can analyse the functions which are highlighted red.
If you use JNGP editor, there is a function list which you can use to do so.
The reason is that those red BJ functions can mostly be inlined, which means you can directly write what's written there.

For example:

JASS:
function SetUnitLifeBJ takes unit whichUnit, real newValue returns nothing
    call SetUnitState(whichUnit, UNIT_STATE_LIFE, RMaxBJ(0,newValue))
endfunction

You see it calls an other function sinde. So you can directly use call SetUnitState(...), just for example.
 
Level 3
Joined
Sep 10, 2012
Messages
39
Good to know I don't need to tie myself in knots trying to prevent leaks that aren't actually leaks. Of course, it seems the function was never actually leaking the way I thought it was - I just hadn't watched the RAM usage long enough. There's a small, initial surge, but it drops and stabilizes quickly, and I was too quick to assume that I was seeing a leak. Although I'm wondering, now, how large most leaks actually are; have they be determined and listed somewhere?

Either way, I am grateful for the information. +rep
 
Level 45
Joined
Feb 27, 2007
Messages
5,578
Although I'm wondering, now, how large most leaks actually are; have they be determined and listed somewhere?
The size of any given single leak (for example in the trigger below), is the size of however many bytes make up the data type that you leaked. Integers are 4 bytes, so if you could leak one it would eat up 4 bytes of your RAM. Unless I'm off my rocker there's no reason this should be different for any other leak, but IDK if all data types are 4 bytes.
  • Events
    • Map Initialization
  • Conditions
  • Actions
    • -------- Only runs once, only leaks 1 object: a location --------
    • Unit - Move Hero 001 <gen> to (Center of (Playable Map Area))
 
Integer is 4 bytes, but other, complex data types, like for example "Unit Group" is some more, and also leaks more for each contained unit.

There is this complex datatype named handle which includes or extends pretty much everything that we need to destroy or care of.
Each handle has an other native data type size, and I can't remember seeing a detailed list of the exact amount. But it's also no so important in the end. Important is that one needs to prevent leaks.

I found this little info from here (not tested myself though):

JASS:
//  Location:  0.361 kb
//  Group:     0.62 kb + 0.040 kb for each unit in the group.
//  Effect:    11.631 kb

You can read this. Maybe I should add a chapter about primitve data types.
 
Level 7
Joined
Oct 19, 2015
Messages
286
The BJ function GetUnitsInRectAll calls the function GetUnitsInRectMatching, which looks like this:
JASS:
function GetUnitsInRectMatching takes rect r, boolexpr filter returns group
    local group g = CreateGroup()
    call GroupEnumUnitsInRect(g, r, filter)
    call DestroyBoolExpr(filter)
    return g
endfunction
As you can see, the function creates a new group, which you then have to destroy yourself to prevent a leak, which you do. The problem with this function is that it leaves a variable pointing to the handle address of the group (the g local variable), so even if you destroy the group itself, its handle address will not get recycled - you get a handle address leak. The solution to this problem would be to use the GroupEnumUnitsInRect function directly. Since this function is called on an existing group, you can just reuse the same group all the time, no need to keep creating and destroying it, which will improve your code efficiency in addition to preventing the leak.
 
Status
Not open for further replies.
Top