1. The poll for our 11th Music Contest is up! Help us choose the most awesome cinematic tracks by casting a vote!
    Dismiss Notice
  2. Melee Mapping contest #3 - Poll is up! Vote for the best 4v4 melee maps!
    Dismiss Notice
  3. The 30th edition of the Modeling Contest is finally up! The Portable Buildings need your attention, so come along and have a blast!
    Dismiss Notice
  4. The Aftermath has been revealed for the 19th Terraining Contest! Be sure to check out the Results and see what came out of it.
    Dismiss Notice

Latest patch doesn't inline?

Discussion in 'Patch Discussion' started by Pinzu, Feb 12, 2019 at 10:03 PM.

  1. Pinzu

    Pinzu

    Joined:
    Nov 30, 2007
    Messages:
    1,148
    Resources:
    3
    Spells:
    2
    Tutorials:
    1
    Resources:
    3
    I'm sitting on the latest wc3 patch and when testing my code methods that should be inlined are not for me, where as for Overfrost who sits on older patch it seem to work fine. Could someone confirm this?

    I've also tested this by removing the use of table and i hit on the OP limit much later, if the method inlined properly there would be no difference between using Table and not using Table in this regard.

     
  2. Retera

    Retera

    Joined:
    Apr 19, 2008
    Messages:
    733
    Resources:
    18
    Models:
    11
    Tools:
    1
    Maps:
    6
    Resources:
    18
    I had this problem so I went to the JassHelper drop-down menu in the Trigger Editor and checked the box for optimizations. Once I had the optimizations running on save, then everything was inlining again.

    Does this work for you?

    I was using the standard Patch 1.30.4 World Editor with no modifications.
     
  3. Pinzu

    Pinzu

    Joined:
    Nov 30, 2007
    Messages:
    1,148
    Resources:
    3
    Spells:
    2
    Tutorials:
    1
    Resources:
    3
    I've tested again and made sure the optimizations was toggled on there is still no difference. Here is an example if you want to test for yourself:

    Code (vJASS):

    scope Sorting initializer Init

        globals
            private constant integer NUM_UNITS = 1000  // CHANGE THIS
            private constant boolean USE_TABLE = true  // CHANGE THIS
            private Table table
            private hashtable ht = InitHashtable()
            private integer up
            private integer down
            private trigger t
            private unit pivot
            private unit other
        endglobals

     
        private function quicksort takes integer first, integer last returns nothing
            if first < last then
                set up = first
                set down = last
                set pivot = table.unit[first]
                loop
                    loop
                        set other = table.unit[up]
                        exitwhen up >= last or TriggerEvaluate(t)
                        set up = up + 1
                    endloop
                    loop
                        set other = table.unit[down]
                        exitwhen  not TriggerEvaluate(t)
                        set down = down - 1
                    endloop
                    exitwhen up >= down
                    set other = table.unit[up]
                    set table.unit[up] = table.unit[down]
                    set table.unit[down] = other
                endloop
                set other = table.unit[first]
                set table.unit[first] = table.unit[down]
                set table.unit[down] = other
                call quicksort(first, down - 1)
                call quicksort(down + 1, last)
                endif
        endfunction
     
        private function quicksort2 takes integer first, integer last returns nothing
                if first < last then
                    set up = first
                    set down = last
                    set pivot = LoadUnitHandle(ht , 0, first)
                    loop
                        loop
                            set other = LoadUnitHandle(ht , 0, up)
                            exitwhen up >= last or TriggerEvaluate(t)
                            set up = up + 1
                        endloop
                        loop
                            set other = LoadUnitHandle(ht , 0, down)
                            exitwhen  not TriggerEvaluate(t)
                            set down = down - 1
                        endloop
                        exitwhen up >= down
                        set other = LoadUnitHandle(ht , 0, up)
                        call SaveUnitHandle(ht, 0, up, LoadUnitHandle(ht, 0, down))
                        call SaveUnitHandle(ht, 0, down, other)
                    endloop
                    set other = LoadUnitHandle(ht , 0, first)
                    call SaveUnitHandle(ht, 0, first, LoadUnitHandle(ht, 0, down))
                    call SaveUnitHandle(ht, 0, down, other)
                    call quicksort2(first, down - 1)
                    call quicksort2(down + 1, last)
                    endif
        endfunction
     
        function Reorder takes nothing returns nothing
            local integer i = 0
            loop
                exitwhen i == NUM_UNITS
                static if USE_TABLE then
                    set pivot = table.unit[i]
                endif
                static if not USE_TABLE then
                    set pivot = LoadUnitHandle(ht, 0, i)
                endif
                call SetUnitX(pivot, i*15 - 1500)
                if i > 1000 then
                    call SetUnitY(pivot, 500)
                else
                    call SetUnitY(pivot, 0)
                endif
                set i = i + 1
            endloop
        endfunction
     
        function Sort takes nothing returns nothing
            if USE_TABLE then
                call quicksort(0, NUM_UNITS - 1)
            else
                call quicksort2(0, NUM_UNITS - 1)
            endif
            call ExecuteFunc("Reorder")
        endfunction

        private function compare takes nothing returns boolean
            return GetPlayerId(GetOwningPlayer(pivot)) < GetPlayerId(GetOwningPlayer(other))
        endfunction
     
        private function Init takes nothing returns nothing
            local integer i = 0
            set table = Table.create()
            loop
                exitwhen i == NUM_UNITS
                static if USE_TABLE then
                    set table.unit[i] = CreateUnit(Player(GetRandomInt(0, 23)), 'hpea', 0, 0, 0)
                endif
                static if not USE_TABLE then
                    call SaveUnitHandle(ht, 0, i, CreateUnit(Player(GetRandomInt(0, 23)), 'hpea', 0, 0, 0))
                endif
                set i = i + 1
            endloop
            set t = CreateTrigger()
            call TriggerAddCondition(t, Condition(function compare))
            call ExecuteFunc("Sort")
        endfunction


    endscope

    With table it can sort 1300 while writing to the hastable directly it can sort 1900 units. If the inlining was happening correctly this difference wouldn't be there or be minimal.
     
    Last edited: Feb 13, 2019 at 6:15 PM
  4. Retera

    Retera

    Joined:
    Apr 19, 2008
    Messages:
    733
    Resources:
    18
    Models:
    11
    Tools:
    1
    Maps:
    6
    Resources:
    18
    So, in order to ensure mine was inlining, I did not do these performance metrics. I simply looked at the output code, and whether or not it had replaced some functions with other functions.

    Have you looked at the output JASS? Later tonight when I get home I can confirm the inlining takes place by posting the before and after output of a sample script.
     
  5. Pinzu

    Pinzu

    Joined:
    Nov 30, 2007
    Messages:
    1,148
    Resources:
    3
    Spells:
    2
    Tutorials:
    1
    Resources:
    3
    Example output is in the first post, I use Ladiks MPQ for that if that is any problem? If I didn't have none-inlined code I wouldn't have done the performance metric ^^

    Here is the above:
    Code (vJASS):

    // scope Sorting begins


       
     function Sorting___quicksort takes integer first,integer last returns nothing
            if first < last then
                set Sorting___up=first
                set Sorting___down=last
                set Sorting___pivot=s__Table___units__getindex(s__Table__get_unit(Sorting___table),first)
                loop
                    loop
                        set Sorting___other=s__Table___units__getindex(s__Table__get_unit(Sorting___table),Sorting___up)
                        exitwhen Sorting___up >= last or TriggerEvaluate(Sorting___t)
                        set Sorting___up=Sorting___up + 1
                    endloop
                    loop
                        set Sorting___other=s__Table___units__getindex(s__Table__get_unit(Sorting___table),Sorting___down)
                        exitwhen not TriggerEvaluate(Sorting___t)
                        set Sorting___down=Sorting___down - 1
                    endloop
                    exitwhen Sorting___up >= Sorting___down
                    set Sorting___other=s__Table___units__getindex(s__Table__get_unit(Sorting___table),Sorting___up)
                    call s__Table___units__setindex(s__Table__get_unit(Sorting___table),Sorting___up, s__Table___units__getindex(s__Table__get_unit(Sorting___table),Sorting___down))
                    call s__Table___units__setindex(s__Table__get_unit(Sorting___table),Sorting___down, Sorting___other)
                endloop
                set Sorting___other=s__Table___units__getindex(s__Table__get_unit(Sorting___table),first)
                call s__Table___units__setindex(s__Table__get_unit(Sorting___table),first, s__Table___units__getindex(s__Table__get_unit(Sorting___table),Sorting___down))
                call s__Table___units__setindex(s__Table__get_unit(Sorting___table),Sorting___down, Sorting___other)
                call Sorting___quicksort(first , Sorting___down - 1)
                call Sorting___quicksort(Sorting___down + 1 , last)
                endif
        endfunction
       
     function Sorting___quicksort2 takes integer first,integer last returns nothing
                if first < last then
                    set Sorting___up=first
                    set Sorting___down=last
                    set Sorting___pivot=LoadUnitHandle(Sorting___ht, 0, first)
                    loop
                        loop
                            set Sorting___other=LoadUnitHandle(Sorting___ht, 0, Sorting___up)
                            exitwhen Sorting___up >= last or TriggerEvaluate(Sorting___t)
                            set Sorting___up=Sorting___up + 1
                        endloop
                        loop
                            set Sorting___other=LoadUnitHandle(Sorting___ht, 0, Sorting___down)
                            exitwhen not TriggerEvaluate(Sorting___t)
                            set Sorting___down=Sorting___down - 1
                        endloop
                        exitwhen Sorting___up >= Sorting___down
                        set Sorting___other=LoadUnitHandle(Sorting___ht, 0, Sorting___up)
                        call SaveUnitHandle(Sorting___ht, 0, Sorting___up, LoadUnitHandle(Sorting___ht, 0, Sorting___down))
                        call SaveUnitHandle(Sorting___ht, 0, Sorting___down, Sorting___other)
                    endloop
                    set Sorting___other=LoadUnitHandle(Sorting___ht, 0, first)
                    call SaveUnitHandle(Sorting___ht, 0, first, LoadUnitHandle(Sorting___ht, 0, Sorting___down))
                    call SaveUnitHandle(Sorting___ht, 0, Sorting___down, Sorting___other)
                    call Sorting___quicksort2(first , Sorting___down - 1)
                    call Sorting___quicksort2(Sorting___down + 1 , last)
                    endif
        endfunction
       
     function Reorder takes nothing returns nothing
      local integer i= 0
            loop
                exitwhen i == Sorting___NUM_UNITS
    //#             static if Sorting___USE_TABLE then
                        set Sorting___pivot=s__Table___units__getindex(s__Table__get_unit(Sorting___table),i)
    //#             endif
    //#             static if not Sorting___USE_TABLE then
    //#                 set Sorting___pivot = LoadUnitHandle(Sorting___ht, 0, i)
    //#             endif
                call SetUnitX(Sorting___pivot, i * 15 - 1500)
                if i > 1000 then
                    call SetUnitY(Sorting___pivot, 500)
                else
                    call SetUnitY(Sorting___pivot, 0)
                endif
                set i=i + 1
            endloop
        endfunction
       
     function Sort takes nothing returns nothing
            if Sorting___USE_TABLE then
                call Sorting___quicksort(0 , Sorting___NUM_UNITS - 1)
            else
                call Sorting___quicksort2(0 , Sorting___NUM_UNITS - 1)
            endif
            call ExecuteFunc("Reorder")
        endfunction

     function Sorting___compare takes nothing returns boolean
            return GetPlayerId(GetOwningPlayer(Sorting___pivot)) < GetPlayerId(GetOwningPlayer(Sorting___other))
        endfunction
       
     function Sorting___Init takes nothing returns nothing
      local integer i= 0
            set Sorting___table=s__Table_create()
            loop
                exitwhen i == Sorting___NUM_UNITS
    //#             static if Sorting___USE_TABLE then
                        call s__Table___units__setindex(s__Table__get_unit(Sorting___table),i, CreateUnit(Player(GetRandomInt(0, 23)), 'hpea', 0, 0, 0))
    //#             endif
    //#             static if not Sorting___USE_TABLE then
    //#                 call SaveUnitHandle(Sorting___ht, 0, i, CreateUnit(Player(GetRandomInt(0, 23)), 'hpea', 0, 0, 0))
    //#             endif
                set i=i + 1
            endloop
            set Sorting___t=CreateTrigger()
            call TriggerAddCondition(Sorting___t, Condition(function Sorting___compare))
            call ExecuteFunc("Sort")
        endfunction

       

    // scope Sorting ends
    function InitCustomTriggers takes nothing returns nothing
        //Function not found: call InitTrig_HashRecyler()
        //Function not found: call InitTrig_ArrayListTable()
        //Function not found: call InitTrig_ArrayListExtension()
        //Function not found: call InitTrig_Table()
        //Function not found: call InitTrig_Sort()
    endfunction
     
    Last edited: Feb 13, 2019 at 11:53 PM
  6. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    5,846
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    There's something setable, too, like "debug mode", in the JassHelper options, which doesn't inline.
     
  7. Overfrost

    Overfrost

    Joined:
    Jan 9, 2019
    Messages:
    82
    Resources:
    0
    Resources:
    0
    How can you state that I'm sitting on an older patch mate? Patch 1.30.3 is not that old. My test-map that is literally only for testing function inlining is maintained in v1.30.3. And as I said previously somewhere else, it's your compiler/settings.

    Want some proof?
    Code (vJASS):
    library Tester initializer Init requires Table

    private function Init takes nothing returns nothing
        local Table tab = Table.create()
        set tab[0] = 1
        set tab[1] = tab[0]
    endfunction

    endlibrary
    Compiled to:
    Code (vJASS):
    //library Tester:

    function Tester__Init takes nothing returns nothing
     local integer tab= s__Table_create()
        call SaveInteger(Table__ht, (tab), (0), ( 1)) // INLINED!!
        call SaveInteger(Table__ht, (tab), (1), ( (LoadInteger(Table__ht, (tab), (0))))) // INLINED!!
    endfunction


    //library Tester ends