GetEnumUnit() vs. local unit u

Narks

Vastly intelligent whale-like being from the stars
Reaction score
90
My function says something like:

DoStuff(GetEnumUnit())
DoMoreStuff(GetEnumUnit())
EvenMoreStuff(GetEnumUnit())


Is it faster to replace GetEnumUnit with a local unit var?
 

Romek

Super Moderator
Reaction score
963
Yes.
 

Narks

Vastly intelligent whale-like being from the stars
Reaction score
90
Do I need to null the unit after? (I think I do?)
 

Romek

Super Moderator
Reaction score
963
Unless it's a hero that won't be removed.

But people tend to null them anyway - It's good practice (And you rarely know whether or not GetEnumUnit() is a hero, unless you check it, which is crappier than just nulling it anyway. :p)
 

Viikuna

No Marlo no game.
Reaction score
265
Yes, variable is probably faster, because function calls are pretty slow and there is 3 of them.

You can use FilterFunction for doing actions:

JASS:


globals
    private filterfunc F
    private group G=CreateGroup() 
endglobals

private function FilterFunction takes nothing returns boolean
   local unit u=GetFilterUnit()
   if someCondition then
        // do actions for u
   endif
   set u=null
   return false
endfunction

private function Action takes nothing returns nothing
   // stuff...
   call GroupEnumUnitsInRange(G,0.0,0.0,1000.,F)
   // no need to do any ForGroups now
   // more stuff
endfunction

// initializer
private function init takes nothing returns nothing
    set F=Filter(function FilterFunction)
endfunction
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
Yes, variable is probably faster, because function calls are pretty slow and there is 3 of them.
Hmm don't be so sure about that, this it is a native function, not a custom one, the difference wouldn't be so much.
 

jig7c

Stop reading me...-statement
Reaction score
123
can you null/remove/destroy intergers/reals by a custom script?
 

Jesus4Lyf

Good Idea™
Reaction score
397
No. Nor do you need to. You can set to 0 if you need to set to 0.

Viikuna, that still executes a callback as opposed to a loop, so I'm not -sure- that it would be faster than a loop. Indeex, a loop is usually better to use, because it gives access to local variables in the caller. For example, damage all units in group... It is at very least more stable to use a loop instead of global carry variables (in case the function is for whatever reason recursive). :D
 

Viikuna

No Marlo no game.
Reaction score
265
I believe that Filter is faster. Loop requires you to call FirstOfGroup and GroupRemoveUnit and stuff like that.

Also null boolexprs leaks something with GroupEnum calls, so if you use it a lot it can be pretty nasty.
 

WolfieeifloW

WEHZ Helper
Reaction score
372
I don't know if this exactly relates but;
FirstOfGroup() can cause problems though I've heard.
If the unit gets out of the group or stuff like that.
Using FoG loops after some time from filling the group isn't totally safe. If a unit who is in the group is removed from the game (using RemoveUnit IIRC), its place in the group will be set to the value
JASS:
null
. So the
JASS:
exitwhen u == null
will return true on its position, though there'd be more units after it in the group. Or at least this is what I recall reading from WC3C some time ago. Using a ForGroup should be safe, me thinks. And you should prolly get rid of CRConditions.
 

Viikuna

No Marlo no game.
Reaction score
265
Yea, but Griffens GroupRefresh kinda fixes that issue.
 

Jesus4Lyf

Good Idea™
Reaction score
397
>Also null boolexprs leaks something with GroupEnum calls, so if you use it a lot it can be pretty nasty.
Proove it, please. Until then I won't believe that one. :)

>FirstOfGroup() can cause problems though I've heard.
>If the unit gets out of the group or stuff like that.
Correct. In this case, a unit can't possibly be removed between the group filling and the loop, so this is irrelevant. ;)

>I believe that Filter is faster. Loop requires you to call FirstOfGroup and GroupRemoveUnit and stuff like that.
I forgot about GroupRemoveUnit. Hmm. ForGroup has a function call and a GetEnumUnit(). 2 for 2? Pending bench tests then, I suppose.

Recall my other point, as it is very relevant: "a loop is usually better to use, because it gives access to local variables in the caller".
 

Romek

Super Moderator
Reaction score
963
The Unit-Removable bug cannot possibly happen with temporary groups, or groups that are filled, and emptied instantly. So that's hardly a problem.

The only time when that'd cause a problem would be when a group is filled over time, then a FoG loop is used to call actions and empty it.
Though this is quite rare. People either fill and empty instantly with FoG, or gradually add units, and use ForGroup.

I don't think any speed difference would be significant by the way. =)
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
Jesus4Lyf said:
Proove it, please. Until then I won't believe that one.
JASS:
scope ThisDoesntLeak initializer init

private function Actions takes nothing returns nothing
    local trigger t=CreateTrigger()
    
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_DEATH)
    call DestroyTrigger(t)
    set t = null
endfunction

//===========================================================================
public function init takes nothing returns nothing
    local trigger trig = CreateTrigger()
    call TriggerRegisterTimerEventPeriodic( trig, 0.01 )
    call TriggerAddAction( trig, function Actions)
endfunction

endscope


JASS:
scope ThisDoesLeaks initializer init

globals
    private group G = CreateGroup()
endglobals

private function Actions takes nothing returns nothing
    call GroupEnumUnitsInRange(G,0,0,0,null)
endfunction

//===========================================================================
public function init takes nothing returns nothing
    local trigger trig = CreateTrigger()
    call TriggerRegisterTimerEventPeriodic( trig, 0.01 )
    call TriggerAddAction( trig, function Actions)
endfunction

endscope


JASS:
scope ThisFixTheLeaks initializer init

globals
    private group G = CreateGroup()
    private boolexpr B_TRUE
endglobals

private function True takes nothing returns boolean
    return true
endfunction

private function Actions takes nothing returns nothing
    call GroupEnumUnitsInRange(G,0,0,0,B_TRUE)
endfunction

//===========================================================================
public function init takes nothing returns nothing
    local trigger trig = CreateTrigger()
    call TriggerRegisterTimerEventPeriodic( trig, 0.01 )
    call TriggerAddAction( trig, function Actions)
    set B_TRUE = Condition(function True)
endfunction

endscope


Sure it's an inaccurate way to know if it leaks or not and how many, but you just have to be check the memory used by the process war3 and that war3 is still running, not a big deal.
 

Viikuna

No Marlo no game.
Reaction score
265
I read it from wc3c (luls) link

And, yea, using locals is nicer than using some global struct instance for filters, but I not so much that I would use loops ( unless they are really really fast ).

And if you feel like benchmarking this, dont forget to tell me which one was faster. If loop is really much faster, I need to start using it.


edit. If you benchmark it, use FilterFunc for actions and global struct instance for passing data ( No ForGroup ) against that loop thingy.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top