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

IsUnitInRange performancewise

Status
Not open for further replies.
Level 5
Joined
May 6, 2013
Messages
125
I never actually knew that it was there and stumbled across it while digging in the common.j for a way to check the race of a unit.

JASS:
constant native IsUnitInRange       takes unit whichUnit, unit otherUnit, real distance returns boolean
constant native IsUnitInRangeXY     takes unit whichUnit, real x, real y, real distance returns boolean
constant native IsUnitInRangeLoc    takes unit whichUnit, location whichLocation, real distance returns boolean

(whatever const means in this context)
Now, judging by it beeing a native funcion and not beeing affected by the incredible overhead that jass (or for that matter, any interpreted scripting language) comes with, its probably faster than manually calculating the distance and comparing it.
On the other hand, when comparing manually, you don't need to use the sqrt if you compare with a constant value, and sqrt's are certainly one of the slower operations.

As for this, does anybody know how those functions are doing and if it's worth using them for constant distances?
 
So if FPS benchmarks are anything to take note of, then the IsUnitInRangeXY/IsUnitInRange natives appear to be faster. Here is a sample of one of the tests I ran:
JASS:
globals
    timer z = CreateTimer()
    real iterations = 10000 /* iterations per second */
    integer count = 35 /* n times per iteration */
    
    /* declare custom globals here */
    unit u = null
    unit v = null
    boolean b = false
    real x 
    real y 
    real d
    real f 
endglobals

struct A

    static method e takes nothing returns nothing
        local integer i = count
        loop
            exitwhen 0 == i
            /* Actions */
            set b = (x-d)*(x-d)+(y-f)*(y-f)<6400
            set i = i - 1
        endloop
    endmethod
    
    static method end takes nothing returns boolean
        call PauseTimer(z)
        return false
    endmethod
    
    private static method onInit takes nothing returns nothing
        local trigger t = CreateTrigger()
        
        call TriggerRegisterPlayerEvent(t, Player(0), EVENT_PLAYER_END_CINEMATIC)
        call TriggerAddCondition(t, Condition(function thistype.end))
        
        call PanCameraToTimed(309, 2005, 0)
        
        /* Perform preliminary setup here */
        set u = CreateUnit(Player(0), 'hfoo', 2, 2, 0)
        set x = GetUnitX(u)
        set y = GetUnitY(u)
        set v = CreateUnit(Player(0), 'hfoo', 100, 100, 0)
        set d = GetUnitX(v)
        set f = GetUnitY(v)
        
        call TimerStart(z, 1./iterations, true, function thistype.e)
    endmethod

endstruct
I would just replace the distance calculation check with IsUnitInRange(u, v, 80).

If I included GetUnitX() instead of default x values, then it would crash at this rate. The current rate is 35 per iteration, at 10k iterations per second. That's why I set it in the initialization, since there are many times where you calculate GetUnitX/Y() earlier in the function for both cases.

The code above yielded fps around 10 that would degrade a little here and there. With IsUnitInRange(), it averaged something around 20 fps.

Now, for IsUnitInRangeXY(), it ranged about 26-32 fps in that setup with one unit created, the check being IsUnitInRangeXY(u, 100, 100, 200). The equivalent check (x-100)*(x-100)+(y-100)*(y-100)<40000, gave results bouncing around 16 to 19 fps. [B]Comments and Personal Criticism:[/B] [LIST][*] I did not report results on the effect of whether it returns true or false. [*] I had chrome and WE running in the background. However, they were in the background for both tests. [*] I ran each test multiple times. A few times were just with restart mission. A few times by closing and testing again, as well. [*] I did not write down the specific results. As you can see above, I just gave approximate ranges. [/LIST] Feel free to comment on my code as well, since I haven't done FPS tests that often. I think it is a good find--and I'll probably use IsUnitInRange() functions from now on since they are easier to use. It makes no practical difference (since you'll never use it at such a high frequency), but it is good to know that there is an alternative. :) Since the tests with manual calculation were consistently lower than the IsUnitInRange equivalent, I suppose you can say that those natives are faster (or rather, require less CPU). But eh, my testing may be off. You may want to test it yourself and be the judge of it.
 
Level 5
Joined
May 6, 2013
Messages
125
Wow, that test actually deserves 10 reps. Unfortunately, i still cant rep you (i have to "spread reps around first"), and i still owe you a rep for the image thingy ^.^

As for the frame test, i never actually did one of them, so i can't really judge over it. I usually use QueryPerformanceCounter for tests like this, but the op limit is kinda stopping me from getting all to big numbers to compare. Someone else will have to say if anything is wrong with your code, as it looks fine to the bloody noob that i am :grin:

Also, a surprisingly clear result. Almost makes me sad considering how many times i used actual distance comparisons. Big thx for that one :thumbs_up:
 
Status
Not open for further replies.
Top