• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[vJASS] [Snippet] Optimizer32

Level 9
Joined
Jun 21, 2012
Messages
432
Created from TimerUtils, T32 and CTL. Optimizer32 is designed to reduce lag caused by start timers a lot of times... :ogre_icwydt:

JASS:
library Optimizer32/*
*************************************************************************************************
*
*   *********************************************************************************************
*
*   */ uses /*
*       */ HandlerCode /* hiveworkshop.com/forums/submissions-414/handlercode-262884/#post2655673
*
*   *********************************************************************************************
*
*   Optimizer32
*   ___________
*   v1.0.1.3
*   by Thelordmarshall
*   
*   One map, less timers... Created from TimerUtils, T32 and CTL.   
*   Optimizer32 is designed to reduce lag caused by start timers a lot of times...
*
*   Periodic time: .031250000 (period used for most spells and systems).
*
*   Pros:
*   _____
*       - Easy way to use.
*       - You can attach integers for each timer "started", similar to TimerUtils.
*       - Use periodic time or not.
*
*   Cons:
*   _____
*       - I haven't found anything bad so far.
*
*   API:
*   ____
*   struct Timer32:
*       - static constant real PERIOD
*           - Public t32 constant period var (Timer32.PERIOD).
*       - static integer data
*           - Public t32 user data (Timer32.data).
*       - static Timer32 expired
*           - Public t32 expired timer (Timer32.expired).
*       - static method start takes integer data, real duration, code c returns Timer32
*           - Start timer: takes integer data, real duration and code c; if duration 
*             is>0 then the timer will be a non periodic time.
*       - static method getExpired takes nothing returns Timer32
*           - Return expired timer.
*       - static method getData takes nothing returns integer
*           - Get the data for your loop function.
*       - method isRunning takes nothing returns boolean
*           - Check if timer instance is running.
*       - method stop takes nothing returns nothing
*           - Stop timer (manually).
*   
*   Credits:
*   ________
*       - Vexorian: TimerUtils.
*       - Jesus4Lyf: T32.
*       - Nestharus: CTL and help me with some tips.
*
*   Notes:
*   ______
*       - All suggestions are welcome.
***********************************************************************************************/
    struct Timer32
        static integer data=0
        static Timer32 expired=0
        static constant real PERIOD=.03125
        private static boolean active=false
        private static timer t32=CreateTimer()
        private static hashtable timerList=InitHashtable()
        private static integer next=0
        private static integer prev=0
        private HandlerCode h
        private real d
        private integer q
        private integer n
        private boolean a
        private boolean p
        
        private static method loop32 takes nothing returns nothing
            local integer i=0
            local thistype this
            loop
                exitwhen(i>next)
                if(HaveSavedInteger(timerList,0,i))then
                    set this=LoadInteger(timerList,0,i)
                    set data=.q
                    set expired=this
                    if(not.p)then
                        set .d=.d-PERIOD
                        if(.d<=0.)then
                            call .h.fire()
                            call .stop()
                        endif
                    else
                        call .h.fire()
                    endif
                endif
                set i=i+1
            endloop
        endmethod
        
        static method getExpired takes nothing returns Timer32
            return expired
        endmethod
        static method getData takes nothing returns integer
            return data
        endmethod
        method isRunning takes nothing returns boolean
            return .a
        endmethod
        
        static method start takes integer data, real duration, code c returns Timer32
            local thistype this
            set next=next+1
            set prev=prev+1
            set this=next
            if(not.a)then
                set .q=data
                set .a=true
                set .d=duration
                set .p=(.d==0)
                set .n=next
                set .h=HandlerCode.get(Condition(c))
                call SaveInteger(timerList,0,next,this)
                if(not active)then
                    set active=true
                    call TimerStart(t32,PERIOD,true,function thistype.loop32)
                endif
                return this
            else
                call .stop()
                debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0.,0.,60.,"[Optimizer32] error: timer32 instance ["+I2S(this)+"] is already started.")
            endif
            return-1
        endmethod
        
        method stop takes nothing returns nothing
            set .a=false
            set .p=false
            set prev=prev-1
            call RemoveSavedInteger(timerList,0,.n)
            if(prev==0)then
                set next=0
                if(active)then
                    set active=false
                    call PauseTimer(t32)
                endif
            endif
        endmethod
    endstruct
endlibrary
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
Yea, this is going to be slower than just using plain old timers. Well, maybe it won't be, but this isn't very well done.


Hint: you should only be using 1 trigger


Stop should push timers to be destroyed on to a stack. After the loop finishes, deallocate the stack.

A lot of methods are added to a the timer several times. Rather than adding them over and over again, they should be registered to a common list. The method only gets evaluated once, then it iterates over each instance that's registered to the core system.

T32 only ever registers a method once, but the method is permanently registered. CTL follows what I stated and it has no extra method calls. Yours isn't even as good as T32 : P. Timer Tools also does what CTL does, except that it does it for any time period.

edit
here's full deallocation

on stop
- if running, push on to stack
- else, deallocate, if empty, stop timer

on loop
- iterate over instances
- deallocate stack
- if empty, stop timer
 
Level 33
Joined
Apr 24, 2012
Messages
5,113
New update.



good... first would have to see which offers the system and then reject it or not .... :ogre_frown:

Sad to say.

Actually, I have proposed this idea to Magtheridon, but he said that "No matter this system features, we will still reject this system. CTL, T32 and TimerUtils already are the best systems we got,we don't need a one map, one timer system".

Actually, he is right. Now imagine if you have 8192 instances of "imaginary" timers executed every 0.031250000 period.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
It's not about there being no more new ideas, it's about there being no more new ideas for timer systems (or at least not ones that are more efficient or usable than existing ones). If you want to experiment with your own philosophy of how a timer system should work, share your thoughts on http://www.hiveworkshop.com/forums/lab-715/

And as I said earlier about standards (http://xkcd.com/927/), there really need to be fewer timer systems so that people who implement JASS resources don't have to also include 9,000 different timer systems.
 
Top