Benchmark IsUnitInGroup vs BooleanArray[GetUnitUserData]

Jesus4Lyf

Good Idea™
Reaction score
397
Comparison:
[LJASS]IsUnitInGroup(Unit,Group)[/LJASS] vs [LJASS]MyArray[GetUnitUserData(Unit)][/LJASS]​

Approximate Results & Conclusions:
  • Tested on Warcraft III Version 1.24b.
  • [LJASS]IsUnitInGroup(Unit,Group)[/LJASS] (best case) takes 1.13 times as long to execute as [LJASS]MyArray[GetUnitUserData(Unit)][/LJASS].
  • [LJASS]MyArray[GetUnitUserData(Unit)][/LJASS] is therefore 12% faster (at worst) than [LJASS]IsUnitInGroup(Unit,Group)[/LJASS].

Comments & Personal Criticism:
  • There was a reasonably low fluctuation demonstrated, showing a stable test.
  • The closer the unit is to the start of the group (ie. in order of units added) the faster the unit is located in the group for the [LJASS]IsUnitInGroup[/LJASS] check. Actually, for 500 units, the time taken to call [LJASS]IsUnitInGroup[/LJASS] on the last unit is 1.84 times the time taken to call [LJASS]IsUnitInGroup[/LJASS] on the first unit.
  • I'm not sure how stable the speed of a global array is in JASS, depending on the number of variables existing.

Code:
JASS:
library Benchmark initializer OnInit
    ///////////////////////////////////////////////
    // Native declarations for stopwatch natives //
    //  - Requires no modified common.j import   //
    ///////////////////////////////////////////////
    native StopWatchCreate  takes nothing returns integer
    native StopWatchMark    takes integer stopwatch returns real
    native StopWatchDestroy takes integer stopwatch returns nothing
    
    /////////////////////////
    // Benchmarking script //
    /////////////////////////
    
    // init
    globals
        unit Unit
        boolean DataSave
        group Group=CreateGroup()
        boolean array MyArray
    endglobals
    
    private function Init takes nothing returns nothing
        local integer i=500
        set Unit=CreateUnit(Player(15),'hpea',0,0,0)
        call GroupAddUnit(Group,Unit)
        call SetUnitUserData(Unit,25)
        loop
            set i=i-1
            call GroupAddUnit(Group,CreateUnit(Player(15),'hpea',0,0,0))
            exitwhen i==0
        endloop
        set DataSave=true
        set MyArray[25]=true
    endfunction
    
    // test
    globals
    private constant string TITLE_A="IsUnitInGroup"
    //! textmacro Benchmark__TestA
        set DataSave=IsUnitInGroup(Unit,Group)
    //! endtextmacro
    private constant string TITLE_B="UserData Boolean Attachment"
    //! textmacro Benchmark__TestB
        set DataSave=MyArray[GetUnitUserData(Unit)]
    //! endtextmacro
    endglobals
    
    // execution
    private function TestA1000 takes nothing returns nothing
        local integer i=1000
        loop
            exitwhen i==0
            set i=i-1
            // Repeat x10
            //! runtextmacro Benchmark__TestA() // 1
            //! runtextmacro Benchmark__TestA() // 2
            //! runtextmacro Benchmark__TestA() // 3
            //! runtextmacro Benchmark__TestA() // 4
            //! runtextmacro Benchmark__TestA() // 5
            //! runtextmacro Benchmark__TestA() // 6
            //! runtextmacro Benchmark__TestA() // 7
            //! runtextmacro Benchmark__TestA() // 8
            //! runtextmacro Benchmark__TestA() // 9
            //! runtextmacro Benchmark__TestA() // 10
        endloop
    endfunction
    private function TestB1000 takes nothing returns nothing
        local integer i=1000
        loop
            exitwhen i==0
            set i=i-1
            // Repeat x10
            //! runtextmacro Benchmark__TestB() // 1
            //! runtextmacro Benchmark__TestB() // 2
            //! runtextmacro Benchmark__TestB() // 3
            //! runtextmacro Benchmark__TestB() // 4
            //! runtextmacro Benchmark__TestB() // 5
            //! runtextmacro Benchmark__TestB() // 6
            //! runtextmacro Benchmark__TestB() // 7
            //! runtextmacro Benchmark__TestB() // 8
            //! runtextmacro Benchmark__TestB() // 9
            //! runtextmacro Benchmark__TestB() // 10
        endloop
    endfunction
    
    private function OnEsc takes nothing returns nothing
        local integer sw
        local integer i
        
        set i=0
        set sw=StopWatchCreate()
        loop
            set i=i+1
            call TestA1000.evaluate() // x10 - 10,000 executions altogether.
            exitwhen i==10
        endloop
        call BJDebugMsg(TITLE_A+": "+R2S(StopWatchMark(sw)*100))
        call StopWatchDestroy(sw)
        
        set i=0
        set sw=StopWatchCreate()
        loop
            set i=i+1
            call TestB1000.evaluate() // x10 - 10,000 executions altogether.
            exitwhen i==10
        endloop
        call BJDebugMsg(TITLE_B+": "+R2S(StopWatchMark(sw)*100))
        call StopWatchDestroy(sw)
    endfunction
    
    ///////////////////////////////
    // Registers the OnEsc event //
    ///////////////////////////////
    private function OnInit takes nothing returns nothing
        local trigger t=CreateTrigger()
        call TriggerRegisterPlayerEvent(t,Player(0),EVENT_PLAYER_END_CINEMATIC)
        call TriggerAddAction(t,function OnEsc)
        call Init()
    endfunction
endlibrary
 

Romek

Super Moderator
Reaction score
963
Give us benchmarks that matter! :p

Jesus4Lyf did some experimenting with groups a while ago, and they seem to be linked lists. Explains the change in speed, as well as some of the functions we have with them. :)
 

Jesus4Lyf

Good Idea™
Reaction score
397
That means IsUnitInGroup is O(n) complexity, right?
I suspect it is a BTree, which I've said before once. It seems to be something more like O(log(n)) than O(n).

>Any idea what sort of comparison there is between looping through an array and using IsUnitInGroup?

>the time taken to call IsUnitInGroup on the last unit is 1.84 times the time taken to call IsUnitInGroup on the first unit.

The time taken to loop through 2 units would be nearly double in an array situation, as opposed to 500 in a IsUnitInGroup situation. It's very efficient. :)

>Give us benchmarks that matter!
This does. It was once thought that attaching booleans to units was a bad idea because IsUnitInGroup was apparently more efficient. Well, that isn't true. :thup:
 

weaaddar

New Member
Reaction score
6
I have to question why you must do the action 10 times in the loop body? Anyway your going to do the thing thousands of times, what difference does it make to make your execution index 10,000 vs 1000 with 10 calls in the body?

While it might be true that array of bools is faster, you can pass a group between functions, which makes it slightly more convenient.
 

Jesus4Lyf

Good Idea™
Reaction score
397
I have to question why you must do the action 10 times in the loop body?
To diminish the add 1 and exitwhen impact. It's vital when you think that there might be more processing time consumed in [LJASS]set i=i+1[/LJASS], [LJASS]exitwhen i==[/LJASS] than in the code you are testing (often the case). :thup:
While it might be true that array of bools is faster, you can pass a group between functions, which makes it slightly more convenient.
Of course. Depends what you are doing. :)
 

Viikuna

No Marlo no game.
Reaction score
265
I'm not sure how stable the speed of a global array is in JASS, depending on the number of variables existing.

I see that you are now benchmarking lots of stuff, so you could also test this.
I remember Cohadar once long time ago complaining about some struct stuff to Vexorian, about how structs use global arrays, which get slower if theres big number of variables existing and stuff like that, dont really remember.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • The Helper The Helper:
    The bots will show up as users online in the forum software but they do not show up in my stats tracking. I am sure there are bots in the stats but the way alot of the bots treat the site do not show up on the stats
  • Varine Varine:
    I want to build a filtration system for my 3d printer, and that shit is so much more complicated than I thought it would be
  • Varine Varine:
    Apparently ABS emits styrene particulates which can be like .2 micrometers, which idk if the VOC detectors I have can even catch that
  • Varine Varine:
    Anyway I need to get some of those sensors and two air pressure sensors installed before an after the filters, which I need to figure out how to calculate the necessary pressure for and I have yet to find anything that tells me how to actually do that, just the cfm ratings
  • Varine Varine:
    And then I have to set up an arduino board to read those sensors, which I also don't know very much about but I have a whole bunch of crash course things for that
  • Varine Varine:
    These sensors are also a lot more than I thought they would be. Like 5 to 10 each, idk why but I assumed they would be like 2 dollars
  • Varine Varine:
    Another issue I'm learning is that a lot of the air quality sensors don't work at very high ambient temperatures. I'm planning on heating this enclosure to like 60C or so, and that's the upper limit of their functionality
  • Varine Varine:
    Although I don't know if I need to actually actively heat it or just let the plate and hotend bring the ambient temp to whatever it will, but even then I need to figure out an exfiltration for hot air. I think I kind of know what to do but it's still fucking confusing
  • The Helper The Helper:
    Maybe you could find some of that information from AC tech - like how they detect freon and such
  • Varine Varine:
    That's mostly what I've been looking at
  • Varine Varine:
    I don't think I'm dealing with quite the same pressures though, at the very least its a significantly smaller system. For the time being I'm just going to put together a quick scrubby box though and hope it works good enough to not make my house toxic
  • Varine Varine:
    I mean I don't use this enough to pose any significant danger I don't think, but I would still rather not be throwing styrene all over the air
  • The Helper The Helper:
    New dessert added to recipes Southern Pecan Praline Cake https://www.thehelper.net/threads/recipe-southern-pecan-praline-cake.193555/
  • The Helper The Helper:
    Another bot invasion 493 members online most of them bots that do not show up on stats
  • Varine Varine:
    I'm looking at a solid 378 guests, but 3 members. Of which two are me and VSNES. The third is unlisted, which makes me think its a ghost.
    +1
  • The Helper The Helper:
    Some members choose invisibility mode
    +1
  • The Helper The Helper:
    I bitch about Xenforo sometimes but it really is full featured you just have to really know what you are doing to get the most out of it.
  • The Helper The Helper:
    It is just not easy to fix styles and customize but it definitely can be done
  • The Helper The Helper:
    I do know this - xenforo dropped the ball by not keeping the vbulletin reputation comments as a feature. The loss of the Reputation comments data when we switched to Xenforo really was the death knell for the site when it came to all the users that left. I know I missed it so much and I got way less interested in the site when that feature was gone and I run the site.
  • Blackveiled Blackveiled:
    People love rep, lol
    +1
  • The Helper The Helper:
    The recipe today is Sloppy Joe Casserole - one of my faves LOL https://www.thehelper.net/threads/sloppy-joe-casserole-with-manwich.193585/
  • The Helper The Helper:
    Decided to put up a healthier type recipe to mix it up - Honey Garlic Shrimp Stir-Fry https://www.thehelper.net/threads/recipe-honey-garlic-shrimp-stir-fry.193595/
  • The Helper The Helper:
    Here is another comfort food favorite - Million Dollar Casserole - https://www.thehelper.net/threads/recipe-million-dollar-casserole.193614/

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top