System Key Timers 2

Jesus4Lyf

Good Idea™
Reaction score
397
You'd better go an post this at wc3c.net, to increase popularity that is. ^^
Funny thing. I'm banned there, last I checked. As in I can see everything, I just can't post. No one sees what I say.

Seems a decent system, though I have no idea how it would be faster than 0x100000 substraction since that is supposed to be the fastest...
Yeah, I lol'd at that. It's simple, really. This system technically doesn't attach at all. :D A little JASS magic. Just check out the Timer Systems in Warcraft III doc if you wish to understand it.

Anyway, I suppose I'm not overly concerned about increasing popularity, because KT2 is basically the best. Therefore, it should get popular by itself (or so the theory goes). However, I'll just drop mentions when I see timers come up. I do want mappers to use it because then maps will be more efficient and quicker to make.
 
Reaction score
91
> Just check out the Timer Systems in Warcraft III doc if you wish to understand it.
Yeah, I read it. Still, it's strange.
Going to test it right now by converting a map of mine from TT to this. Will do it roughly to see if this is efficient and safe. :p You pointed out that only specific periods can be used with KT. Are 0.02 and 0.035 fine?
 

Jesus4Lyf

Good Idea™
Reaction score
397
Yes. Periods can range from 0.005 to 40.995, and must be no finer than 0.005 of a second. So 0.005, 0.01, 0.015, 0.02... All fine.

0.023? Bad.

Let me know how the conversion goes! ^_^

The advantage of changing from TT to KT2 is if you port your spell to another map (or submit it on The Helper and someone uses it) where the mapper prefers a different period in their spells, it doesn't matter, they won't clash (like they would do in TT unless they were coded around the period constant). :D
And realistically there is no disadvantage.

So my hopes are this system will help the community share spells, while not losing but even gaining efficiency.
 

Azlier

Old World Ghost
Reaction score
461
Well, I read through that Word document again, and GetData is faster than H2I attaching. You don't tell me exactly why. You just tell me it's JASS magic... where's the magic? Or is that a secret?
 
Reaction score
91
> 0.023? Bad.
Why? I have a little system that handles distances and is highly possible that such a period be used more than once in the game (or like 1.23, 1.66, etc.). Is that fatal? Here's a part of it:

JASS:

    local real x1 = GetUnitX(d.cast)
    local real y1 = GetUnitY(d.cast)
    local real x2 = GetUnitX(d.targ)
    local real y2 = GetUnitY(d.targ)
    local real xx = x1 - x2
    local real yy = y1 - y2
    local real r  = SquareRoot(xx * xx + yy * yy)
    local real tr = r / d.speed    
    call KT_Add(function Callback, d, tr)


So you see, tr can be any period (not above 2-3 seconds). Though, when I tested it in-game it seemed to work without a problem.

Anyway, the conversion is done and the system works pretty fine. I guess it can get more usage soon enough. :)
 

Jesus4Lyf

Good Idea™
Reaction score
397
If my explanation was lacking or missing, here's a better one.

In the loop, instead of local integer i to loop through, a global is used.
Your functionality is stored in trig.
Your data is stored in data.
Can you see that the functionality and data are stored in the same way, parallel, instead of attaching the data to your code? H2I, when it loads your data, you pass in GetExpiredTimer() which takes time to execute (lol not much). Key Timers 2 does has your data loaded effectively as part of its loop, directly from an array (without calling H2I on anything, let alone GetExpiredTimer), rather than your code executing commands to retrieve the data. The GetData function simply loads your data the same way as the loop loads your code.

The technical explanation: Key Timers 2 uses global variables and concurrent threading, instead of separately loading.


Edit instead of double post:
> 0.023? Bad.
Why? I have a little system that handles distances and is highly possible that such a period be used more than once in the game (or like 1.23, 1.66, etc.). Is that fatal?
I'm starting to think I'd better inbuild some protection against it. The problem is if you use a period of 0.023, let's say, and THEN use a period of 0.02 in another spell, then the 0.02 spell will actually use the period of 0.023 (because thats the period used in the 0.02 range). I think I'll embed protection in the next version so if you say 0.023, it rounds it down to the nearest 0.005 automatically. For that reason.
 

emjlr3

Change can be a good thing
Reaction score
395
so i guess the conclusion is H2I is very slow
 

Jesus4Lyf

Good Idea™
Reaction score
397
> so i guess the conclusion is H2I is very slow
By comparison. The GetData function call of KT2 is an array read - it may even get inlined. H2I does some processing, THEN does an array call. If you compare H2I to it, then yeah it's... very slow. Especially because you need safety systems to make it stable and usable too.

Personally I stopped using H2I completely in my maps when I started working on Savage Creed due to a handle count of over 10,000.
I use GetTriggerExecCount for attaching to triggers, Key Timers 1 & 2 for attaching to timers and GetUnitUserData for attaching to units.
 

emjlr3

Change can be a good thing
Reaction score
395
how does yours compare to a struct stack/loop

i.e.

JASS:

struct Data
endstruct
globals
  Data array D
  integer Count
  timer T
endglobals
function TimerCallback
  local integer i = 1
  local Data d

  loop
    exitwhen i>Count
    set d = D<i>
    set i = i + 1
  endloop
endfunction
function Start
  if Count==0 then
    call TimerStart(T)
  endif
  set Count = Count + 1
  set D[Count] = your_struct
endfunction</i>


so you would have to compare the execution time of your start/get functions compared to

JASS:
  
  if Count==0 then
    call TimerStart(T)
  endif
  set Count = Count + 1
  set D[Count] = your_struct


and

JASS:
  
  loop
    exitwhen i&gt;Count
    set d = D<i>
    set i = i + 1
  endloop</i>


IMO

I'd just like to see, because Cohadar said a struct stack/loop method was faster then TT, and the fastest method there is, when I asked him a few weeks ago

I'm starting to think I'd better inbuild some protection against it. The problem is if you use a period of 0.023, let's say, and THEN use a period of 0.02 in another spell, then the 0.02 spell will actually use the period of 0.023 (because thats the period used in the 0.02 range). I think I'll embed protection in the next version so if you say 0.023, it rounds it down to the nearest 0.005 automatically. For that reason.

I was actually thinking this - its added overhead, but it makes it idiot proof, or dumb mistake proof

what is the limit to the total number of threads per timer interval, 8191?

I actually read through the majority of your paper btw
 
Reaction score
332
Despite the incorrect use of the term, Key Timers 1, TT, and Key Timers 2 are not timer attachment systems. KeyTimers 1 does something totally mundane that people have been doing inline for ages (see emjlr3's post), and TT is about the same except that it allows you to provide callback functions, which makes it much more useful. Key Timers 2 goes one better and allows you to supply a period, but the usefulness of this feature is questionable.

Attempting to benchmark Key Timers or TT against attachment systems like HSAS or ABCT is meaningless because it does not reflect the typical or correct usage of these systems. To see what I mean, look at the map attached to this post that simulates timed life with timers. On the left-hand side of the map, timer attachment is used and produces the correct behavior. On the right-hand side of the map, Key Timers is used and produces incorrect behavior.

Personally I stopped using H2I completely in my maps when I started working on Savage Creed due to a handle count of over 10,000.
I use GetTriggerExecCount for attaching to triggers, Key Timers 1 & 2 for attaching to timers and GetUnitUserData for attaching to units.

This borders on superstition. H2I works no matter how many handles you have. If you are attaching, you can use H2I with gamecache for no limits, or with vJass extended arrays for no practical limits. Either way is better than using some kludge like GetTriggerExecCount for attachment.
 

Attachments

  • Test.w3x
    17.5 KB · Views: 297

Jesus4Lyf

Good Idea™
Reaction score
397
how does yours compare to a struct stack/loop
That's EXACTLY what KT1 is. A text macro for inplementing that. :) (Therefore KT2 is half as fast.)
Of course, dealing with those interfaces can be complicated and take a long time for intermediate JASSers, for which KT2 is aimed at. Especially if they write them by hand.

I was actually thinking this - its added overhead, but it makes it idiot proof, or dumb mistake proof
Not really! Firstly it would be so fast it would be unnoticable. Secondly it only only run ANY extra code the first time each period is used. It would be a modulo thing.

what is the limit to the total number of threads per timer interval, 8191?
As per the "cons" of this system, 400 instances per period max, 20 different periods max. 400x20=8000. Heh...

Keep in mind the purpose of this system is mostly for user interface. If you need speed and don't mind complexity, struct loop/KT1 is the way to go, with of course 8191 limit per declaration.

I actually read through the majority of your paper btw
Appreciated. :)

>TheDamien
Everything you're talking about has been documented in Timer Systems in Warcraft III (including that they are not timer attachment systems in the sense of attaching data to timers). The doc says for the exact thing you're testing that KT 1 & 2 cannot do it (executing the first time exactly after the period after the add function is called). It's clearly stated and documented in sections 2.3, 3.1, and 5, and tells you to use TimerUtils instead.

H2I works no matter how many handles you have.
My point wasn't just stability. ExecCount is both more stable and faster for attaching to triggers when carefully applied. But this is off topic so I request no replies further on this issue. :)

PS. Thanks for the test demonstration. :D
 
Reaction score
332
Everything you're talking about has been documented in Timer Systems in Warcraft III (including that they are not timer attachment systems in the sense of attaching data to timers). The doc says for the exact thing you're testing that KT 1 & 2 cannot do it (executing the first time exactly after the period after the add function is called). It's clearly stated and documented in sections 2.3, 3.1, and 5, and tells you to use TimerUtils instead.

Admittedly, I didn't read the document, but my main concern was that people would see this system and get it confused with real timer attachment systems. Given the recent course of this thread, for example, I'm thinking that many people are not sufficiently aware of the difference between KT_Add and ABCT_Start. This confusion is enhanced by the fact that you are benchmarking entirely different types of systems against each other, which is not purposefully misleading but potentially misleading all the same.

The bottom line is that this is a good system, but not a great system, and certainly not some sort of silver-bullet. The ability to provide a period is not a very useful or significant advantage over TT, but may prove useful for some trivial tasks.

PS. Thanks for the test demonstration. :D

You're welcome.
 

Akolyt0r

New Member
Reaction score
33
I really dont think a system like this is needed ...
If you really need speed ...do a struct array loop + static timer ...and you are fine ..

for most other tasks TimerUtils are the way to go ...much more flexible than this here...

The limit of 20 different periods is just to low to make this one here useful ...

And having 2 systems for timers in a map is just gay...

about speed: yeah this might be a little faster ...than TimerUtils (H2Icall + Arrayllookup) but TriggerEvaluate isnt that fast aswell ...so it isnt much difference ...
 

Jesus4Lyf

Good Idea™
Reaction score
397
My pov is simply that for most purposes, KT2 is the best balance of speed and functionality. Certainly the fastest multi-period timer system to date, afaik. That alone, to me, says it has value.

And honestly, I absolutely agree. You want speed and you're not a noob? Go use KT1/write your own (same thing). But this system allows intermediate JASSers to use a solid, stable interface without worrying about technical details. It also happens to be the fastest, so far.

Keep in mind this is ~21% faster than TimerUtils Blue, according to the tests, and that would be the system those mappers would otherwise likely be using.

I would not hesitate in suggesting this system to new/intermediate JASSers, especially for spells. I'm thinking I'm even going to use it for spells, just because it's so quick to use. And you don't need to worry about technical criteria like TU Red or something. And beyond that, it's faster.
 

Jesus4Lyf

Good Idea™
Reaction score
397
I'm glad to see Vexorian agrees with most of what I've said. But he should do read through the benches and doc thoroughly first, still. At his first post, he hadn't read the doc.

I hope that he will consider the bench rather appropriate, or at least understand why it is exactly the way it is.

The reason for the 1.0/0.0 difference he highlighted is that KT2 doesn't support 0.0 period (rightfully so). The reason it says 1.0 is so it can attach the data, but if you look inside the system it's modified to use 0.0 also. :)

Just the best solution I could think of at the time to make the test work.

By the way, everything being said has already been documented. I don't believe he's written a single post after reading the whole document yet, because he hasn't noted that TimerUtils is recommended specifically in the case that you need the first proc of the timer exactly after the period passes. :)

PS. Increasing the max periods really isn't particularly hard. I just haven't known a need for it yet.

Edit: Tried contacting Vex, but he left IRC when I showed up.
 

Azlier

Old World Ghost
Reaction score
461
>At his first post, he hadn't read the doc.

Have you seen his next two posts, yet?
 

Jesus4Lyf

Good Idea™
Reaction score
397
Yes.

He says there's a flaw in the test, which is "Instead the other systems don't get this advantage". Actually, that was the premise behind designing Key Timers 2. It has an advantage over other systems.

Now I'm going to say this quite clearly. When someone comes to me and tells me there is actually a problem with my system that needs fixing, in that it does not fulfill what I've said of it in my documentation, then that problem will be fixed. Until then, this system is solid and does exactly what's said of it, and its benchmarks are relevant and correct.

You don't have to look far to realise he's not paying attention. For example:
>Why have 3 timers going in the background when you can have 1?
Sometimes you can't have just 1.
I've said that sometimes you can't. In fact, I even went so far as to explain when you can't. It's even factored into my recommendations, so that people who follow them can NEVER come across a certain bug he keeps harping on about, because he did something the documentation clearly states multiple times not to. (See section 5.)

The horribly inflated percentages show that there must be something broken with the benchmark - I should take a real good look at it later - or that he doesn't know how to calculate percentages.
See, he's just wrong there. Demonstration: 5.9 microseconds/1.3 microseconds = 4.538. In other words, 454% execution time. In other words, an additional 354%. Problem? And no one has prooved that my "add" benchmark is flawwed (and I doubt they will, except perhaps for ABCT which is slower than TU for looping anyway).

Nonetheless, thanks for your concerns. I'll do my best to answer them quickly and keep everyone at ease. :)

Edit: Updated the document to fix the issues Vexorian rightly highlighted. Thanks to him for that. :D
Released Version 1.02.
 

Azlier

Old World Ghost
Reaction score
461
[Vex Quote]
Here’s the other downside. Since they all execute together, if you say “Every 1 second, call function ProcessMySpell” using a multi-instance timer system, then the first time it executes may be anywhere between 0.001 and 1 second, because the timer it will be attached to is likely to be already firing. For most cases, I’ve found this doesn’t matter, because it will still be executed the same number of times in 10 seconds (considering spell balance). Also, sometimes it simply doesn’t matter because it’s controlling AI, or counting down a cooldown to see when it expires, which doesn’t need to be precise usually anyway.


So the guy knew about the bug and still released the system? Minimizing this issue is not the way to work around it. Releasing a bugged system on purpose just in the name of speed is just not right. It may not be a big issue when the timeout is less than a second, but it really is an issue later.

We are talking about spells here, and neglecting the visual part is really a bad mistake to make. Timers need to be accurate when you are synchronizing animation and movement and stuff. Sometimes you need something to happen exactly 0.45 seconds after a special effect has been created. Period. If this code is not executed after 0.45 seconds it will look bad. Balance is far from being the only problem here, But for large timeouts it truly is. If you want to make a spell like flame strike. Sometimes it will do the damage after 3 seconds and sometimes after 0.4 seconds, this is just wrong.[/Vex Quote]

And this?
 

Jesus4Lyf

Good Idea™
Reaction score
397
TheDamien raised the same issue.
The doc says for the exact thing you're testing that KT 1 & 2 cannot do it (executing the first time exactly after the period after the add function is called). It's clearly stated and documented in sections 2.3, 3.1, and 5, and tells you to use TimerUtils instead.

By the way, this is the 3rd time or so I've addressed this in about 4 posts.

Anyway, if you read even just that little bit of what he quoted from my doc, right there in your own post, you will know the absolute sum of the problem, how to avoid it, why it usually doesn't make a difference, and why I've recommended what I have.

>Sometimes you need something to happen exactly 0.45 seconds after a special effect has been created.
Check section 5, and see what I recommend for this exact situation. It's TU, not KT2. Therefore, he either hasn't read it, or is just ignoring it to purposefully take irrelevant shots at this system.

Edit: Definition of a bug: "a programming error, that causes a program to behave in an unexpected way." Therefore, this is not actually a bug. It's the known tradeoff for bulk processing. It is not a mistake, nor is the result unexpected. :)
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      • Ghan
        Administrator - Servers are fun

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top