System Timer32

koeienboei

Member
Reaction score
4
Code:
native GetMouseTerrainY takes nothing returns real
native GetMouseTerrainX takes nothing returns real

scope Dash

private struct Dash
    real dx
    real dy
    unit subject
    private method periodic takes nothing returns nothing
        call SetUnitX(subject, GetUnitX(subject) + dx)
        call SetUnitY(subject, GetUnitY(subject) + dy)
    endmethod
    implement T32x
    private static method create takes unit which, real speed, returns thistype
        local thistype this = thistype.allocate()
        set this.dx = speed*1000 * T32_PERIOD
        set this.dy = (1-speed)*100 * T32_PERIOD
        set this.subject = which
        call this.startPeriodic()
        return thistype
    endmethod
    private method destroy takes nothing returns nothing
        call this.stopPeriodic()
        call this.deallocate()
    endmethod
endstruct

private function Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A002' ) ) then
        return false
    endif
    return true
endfunction

private function Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local real speed = (GetUnitX(u)-GetMouseTerrainX()) / ((GetUnitY(u)-GetMouseTerrainY())
    local Slide s = Slide.create(u, speed)    
endfunction

//===========================================================================
function InitTrig_Dash takes nothing returns nothing
    local trigger Dash = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( Dash, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( Dash, Condition( function Conditions ) )
    call TriggerAddAction( Dash, function Actions )
endfunction

endscope

This is the error:
Member redeclared : destroy
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
JASS:
library foo requires TimerUtils

	private struct Data

		private integer tick=0
		private unit    killer

		private method periodic takes nothing returns nothing
			set this.tick=.tick+T32_PERIOD
			if(tick==T32_FPS*5(then
				if (UnitAlive(this.killer)) then
					call KillUnit(this.killer)
					call this.stopPeriodic()
				endif
			endif
		endmethod

		private static method actions takes nothing returns nothing
			local thistype this=thistype.create()
			set this.killer=GetKillingUnit()
			call this.startPeriodic()
		endmethod

		private static method onInit takes nothing returns nothing
			// register a death event
			// register thistype.actions as a callback
		endmethod
	
		implement T32x // <--- that is what actually adds it

	endstruct

endlibrary


:thup:


JASS:
library foo requires TimerUtils


That made me lol. :p
 

koeienboei

Member
Reaction score
4
Ok jasshelper updated.. new problem:
Slide is not of a type that allows . syntax

I dont know how to rewrite it without . syntax..

Can you help me? :rolleyes:
 

tooltiperror

Super Moderator
Reaction score
231

Nestharus

o-o
Reaction score
84
This is currently inaccurate : |

[ljass]public constant real PERIOD=0.03125[/ljass] is bad.

Change it to
[ljass]public constant real PERIOD=0.031250000[/ljass]

JASS is screwy... your current value is .031250002. Adding those 0s in will give the correct value... yes, JASS reals are totally fudged up..
 

Weep

Godspeed to the sound of the pounding
Reaction score
400
your current value is .031250002.
Dude.

It will drift by 1 second in shy of 16 years.
Or a frame at 60fps in a bit over 3 months.
How long would it take for JASS to no longer consider the time elapsed == to the time T32 thinks has elapsed with the same number of significant digits as its current interval specification?


I suppose he might as well add a few zeroes on the number if and when he updates it for an important reason. Or would that affect performance, like longer function names do? :nuts:
 

Bribe

vJass errors are legion
Reaction score
67
T32 is faster than T32x because people would only call .stopPeriodic() from the .periodic method which generates function proxies that get evaluated through triggers instead of called naturally. Same problem with AIDS users who run the textmacro at the top of the struct. Implement T32 at the bottom of the struct, same with AIDS, to avoid this problem.
 

Jesus4Lyf

Good Idea™
Reaction score
397
T32 is faster than T32x because people would only call .stopPeriodic() from the .periodic method which generates function proxies that get evaluated through triggers instead of called naturally.
Your logic is right but your conclusion is not - T32x has a faster iteration speed than T32, which occurs many times compared to the once the proxy call to .stopPeriodic() is made. That makes T32x faster in general, I'd say. Obviously there is a measurable number of ticks at which this occurs in reality, but considering these things fire 32 times per second...

Oh, except one thing:
people would only call .stopPeriodic() from the .periodic method
I strongly disagree. Combining TU and T32 to make effects last x seconds is probably a nice solution to all of this (call .stopPeriodic() from TU callback).
 

Bribe

vJass errors are legion
Reaction score
67
> call .stopPeriodic() from TU callback

I see the advantage of that; more optimal than comparing an array to track the duration, just kill it when the timer actually expires.

I think Nestharus is working on something that could kill TimerUtils, at least for what I use it for. Perhaps I'll find myself using two timer systems in a future script ;)
 

NeuroToxin

New Member
Reaction score
46
<3 I just figured out how to use this, oh, and I have fun defending you Jesus :p, Sometimes people ridicule your systems, then I make them feel like assholes.
 

emjlr3

Change can be a good thing
Reaction score
395
Yo HeyZeus, or someone in the know, please enlighten me

How is this faster then a struct array stack? (assuming only 1 spell, aka 1 timer)

It was always common knowledge that the struct array stack trumpt all other timer attachment like systems

but then I always had a problem with that from the get go, for instance, lets say I was one spell, one instance - the overhead for say timerUtils red data retrieval is:
JASS:
GetHandleId(t)-OFFSET


where as with say a struct array stack, the overhead would be:

JASS:
loop
  exitwhen i&gt;N
  set D=struct
  // use D
  set i=i+1
endloop


for one instance of that one spell. I'd imagine the array would do more work (or take more time), where as lets say you had 8 or 10 going at once, then you can start to see the additive speed increase by eliminating the now native h2i (which maybe is fast now?) and the multiple timer events - but at what point does the overlap take place? who knows?

having said that, the loop overhead still exists in this system, as well as one trigger evaluation and then a function call for each instance (along with some other jibberish I don't get), something like this:
JASS:
call TriggerEvaluate(T)
loop
  exitwhen i&gt;N
  call useData()
  // do some more overhead jibberish
  set i=i+1
endloop


any who, where does the speed increase come from, or is it simply from less periodic timer events firing?
 

Bribe

vJass errors are legion
Reaction score
67
Supposedly one timer expiring constitutes the overhead of a trigger evaluation, but Timer32 also uses trigger evaluation to fire for all structs, so I also fail to notice the speed difference.

If Jesus4Lyf plans to do any updates, allowing users to have direct access to the evaluated method will allow greater control, such as declaring locals in the evaluated method instead of declaring them from the periodic method... if there are lots of local variables, it becomes more efficient to just use a single timer manually.

The module could be "StructTimer" and look like this:

JASS:
module StructTimer
    private static method onInit takes nothing returns nothing
        call TriggerAddCondition(Trig,Condition(function thistype.periodicLoop))
    endmethod
endmodule
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
Yo HeyZeus, or someone in the know, please enlighten me

How is this faster then a struct array stack? (assuming only 1 spell, aka 1 timer)

It was always common knowledge that the struct array stack trumpt all other timer attachment like systems

but then I always had a problem with that from the get go, for instance, lets say I was one spell, one instance - the overhead for say timerUtils red data retrieval is:
JASS:
GetHandleId(t)-OFFSET


where as with say a struct array stack, the overhead would be:

JASS:
loop
  exitwhen i&gt;N
  set D=struct
  // use D
  set i=i+1
endloop


for one instance of that one spell. I'd imagine the array would do more work (or take more time), where as lets say you had 8 or 10 going at once, then you can start to see the additive speed increase by eliminating the now native h2i (which maybe is fast now?) and the multiple timer events - but at what point does the overlap take place? who knows?

having said that, the loop overhead still exists in this system, as well as one trigger evaluation and then a function call for each instance (along with some other jibberish I don't get), something like this:
JASS:
call TriggerEvaluate(T)
loop
  exitwhen i&gt;N
  call useData()
  // do some more overhead jibberish
  set i=i+1
endloop


any who, where does the speed increase come from, or is it simply from less periodic timer events firing?

Well, the speed increase comes from quite a few things. First of all, the loop actually doesn't involve that much:
JASS:
private static method PeriodicLoop takes nothing returns boolean
    local thistype this=thistype(0).next
    loop
        exitwhen this==0
        call this.periodic()
        set this=this.next
    endloop
    return false
endmethod


It just involves array look ups, variable setting, and a function call. Even for one instance, this is pretty fast. However, remember that that is not the only thing to consider. There is also the release() method (which is a lot faster than TimerUtils) and the create() method (which is also faster than creating a timer). Overall, for a standard timer utils kind of system, you would first have to use NewTimer() and then use SetTimerData(). On the loop, you would have to then use GetTimerData() per loop. In the end, you would also have to use ReleaseTimer(). Internally, those functions call other natives, while Timer32 simply sets variables and does array look-ups. So I'd say the difference would kick in even during the first instance.

However, that is when comparing to TimerUtils. When comparing it to a standard struct stack, it also has a better means of setting and retrieving data. (there are no arithmetic operations)

having said that, the loop overhead still exists in this system, as well as one trigger evaluation and then a function call for each instance (along with some other jibberish I don't get), something like this:

The system does it a little differently. Also, the number of trigger evaluations is actually 1 per loop of the timer, not 1 per instance. ;) It will evaluate all instances, yes, but keep in mind that in those cases, thistype(0).next = 0 so it will immediately exit the loop, which is hardly any overhead, even in the most extreme of cases.

All in all, this system is meant to be looked at as a big picture. One timer for everything is fast and efficient. As you get more and more instances, the efficiency of this system really starts to shine. :D It has its drawbacks, but in those cases you can use TimerUtils. This is meant for the common periodic, and in most cases will suit your needs.

Also, nice to see that you are back emjlr. ;D

Supposedly one timer expiring constitutes the overhead of a trigger evaluation, but Timer32 also uses trigger evaluation to fire for all structs, so I also fail to notice the speed difference.

If Jesus4Lyf plans to do any updates, allowing users to have direct access to the evaluated method will allow greater control, such as declaring locals in the evaluated method instead of declaring them from the periodic method... if there are lots of local variables, it becomes more efficient to just use a single timer manually.

The module could be "StructTimer" and look like this:

JASS:
module StructTimer
    private static method onInit takes nothing returns nothing
        call TriggerAddCondition(Trig,Condition(function thistype.periodicLoop))
    endmethod
endmodule

At that point, you should just inline T32. If you really really want control, then just inline it and use the same methods. However, the speed difference is marginal. Also keep in mind that it will generate the local variables even when there are no instances to fire, so it is not the best idea to have it like that. It can be faster, but the interface would just be weird, and not to mention user unfriendly. :p

EDIT: Nvm, I see what you mean.
 

Nestharus

o-o
Reaction score
84
This should never be inlined unless only 1-2 resources in the entire map are using it (guess, but probably very close).
 

Jesus4Lyf

Good Idea™
Reaction score
397
Good to see you, emjlr3. :)

PurgeandFire is on the money, here:
Even for one instance, this is pretty fast. However, remember that that is not the only thing to consider. There is also the release() method (which is a lot faster than TimerUtils) and the create() method (which is also faster than creating a timer). Overall, for a standard timer utils kind of system, you would first have to use NewTimer() and then use SetTimerData(). On the loop, you would have to then use GetTimerData() per loop. In the end, you would also have to use ReleaseTimer(). Internally, those functions call other natives, while Timer32 simply sets variables and does array look-ups. So I'd say the difference would kick in even during the first instance.

However, that is when comparing to TimerUtils. When comparing it to a standard struct stack, it also has a better means of setting and retrieving data. (there are no arithmetic operations)



The system does it a little differently. Also, the number of trigger evaluations is actually 1 per loop of the timer, not 1 per instance.
All of that is good, but the bolded part is the key. All the "struct stack loops" are added to once trigger, which gets evaluated, which is the lowest overhead you can have on a function call, off memory. One timer per loop makes overhead of the timer expiring + function call, with T32 there is only one timer firing and the function calls all come from one trigger evaluate, in other words machine code loops through the loops and calls them each instead of jass code (inside the TriggerEvaluate).

This makes the overhead lower for empty loops or loops with one instance. It was the trick I used in KT2 to make it faster than TU, but then I combined that with a stack loop which I heavily optimised. It is possible to get this faster by inlining the .periodic() method and doing it all by hand, but it is not worthwhile.

Feel free to ask more questions, always! :)

Edit:
Yo HeyZeus, or someone in the know, please enlighten me

How is this faster then a struct array stack? (assuming only 1 spell, aka 1 timer)
To answer this more directly, it's probably much the same. Function call vs generally faster looping method.
 
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