• 🏆 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!

[Snippet] TemporaryHeroAttribute

Level 17
Joined
Apr 27, 2008
Messages
2,455
Well, again, TimerUtils or any X timer solution is the most logical way.
As stated multiple times it's not because your way doesn't lag that it means it's the way to go.
Using TimerUtils is not complicated at all, and the user of this code don't need to understand how to use TU, ofc he has to know how handle libraries requirements, but really if he can't handle that stuff, he shouldn't use vJass at all.

As said if i was a mod i would reject it just for that (in fact i did it on a resource for the same reason on a forum where i am a jass moderator), hopefully here i'm not.
 

Cokemonkey11

Code Reviewer
Level 29
Joined
May 9, 2006
Messages
3,522
As said if i was a mod i would reject it just for that (in fact i did it on a resource for the same reason on a forum where i am a jass moderator), hopefully here i'm not.

Yep, you've made your opinion very clear. But that's your opinion (and it's a shit one, too). It's a good thing you're not a moderator or useful scripts like this would be rejected so you can fulfill your own elitist, illogical agenda.

The fact of the matter is that this script is shorter than TimerUtils, and using TimerUtils won't make it faster.

The fact is that the periodic function does exist for a reason. The reason is that duration-=fidelity, and that's the whole point.

If you don't like it, don't use the script, but bashing my methods for creating useful content is not helping anything except your own agenda, and I don't appreciate it.
 

Cokemonkey11

Code Reviewer
Level 29
Joined
May 9, 2006
Messages
3,522
You take it too much for you, you are not objective. I'm not bashing, just saying facts.
I don't care who is writing the script, only how it's written.
The fact is that TimerUtils is used heavily and should be used here.

In my opinion, TimerUtils is being used because no one has made anything better.

If I wanted to recycle timers I'd make my own system, and it definitely wouldn't make 256 timers on initialization, nor would it use a hashtable.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Imho i've done something better than TimerUtils, but it was graveyarded for a good reason, because TimerUtils is heavily used.
Again you're overevaluating the cost of using an hashtable, but meh you won't change your mind anyway, so this time that's truly my last words on it.
 

Cokemonkey11

Code Reviewer
Level 29
Joined
May 9, 2006
Messages
3,522
Imho i've done something better than TimerUtils, but it was graveyarded for a good reason, because TimerUtils is heavily used.

Are you talking about TimerStack? I just spent some time reading it as well as some of the replies to it.

It's about a thousand times better than TimerUtils. I don't understand why it would be graveyard'd actually. It doesn't belong there.

The people arguing that you have to match the API of TimerUtils are full of shit. The people saying TimerUtils is better/more useful are also full of shit.

I wouldn't make it the same way (I'd do it without a hashtable because if I were making a timer system I wouldn't be making it so people can store data on a timer) but that's beside the point.

I think the criteria for an "accepted" submission should be reduced quite a bit.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Well, simply because it doesn't matter that much, and TU is heavily used.
It's fine to use it personally but it's too much for a public resource, because it needs to much codes edits.
It's just too late, it would be better to use the fixed version of TU by Mag.

I wouldn't make it the same way (I'd do it without a hashtable because if I were making a timer system I wouldn't be making it so people can store data on a timer) but that's beside the point.

Without an hashtable you have to make sure it will fit in an array, so preload X timers is the safest way.
And if you can't store data on a timer then how the hell would you use the timer ?
 

Cokemonkey11

Code Reviewer
Level 29
Joined
May 9, 2006
Messages
3,522
Well, simply because it doesn't matter that much, and TU is heavily used.

That's such a dogshit excuse. There are plenty of people, probably 75% of jass users, who don't regularly use TimerUtils.

It's fine to use it personally but it's too much for a public resource, because it needs to much codes edits.

Who says it's for editing? You read the API, start a new map and use a new system. People aren't forever tied to TU just because they understand it.

It's just too late, it would be better to use the fixed version of TU by Mag.

Maybe, but that's no reason to graveyard your script. You can't say that mag's is "better" than yours.

Without an hashtable you have to make sure it will fit in an array, so preload X timers is the safest way.

Nope.. You just replace the hashtable with an array. So it has to be less than what? 8000 timers? I think that won't be a problem. I'd make it with 0 preloaded imo.

And if you can't store data on a timer then how the hell would you use the timer ?

NewTimer gets a timer.... you can store all the trash you want on it after you've gotten it.

Making TU have a hashtable index is like making a new version of CreateTrigger() that lets you add references to it. Surely it's useful somewhere, but important/worthwhile? Definitely not.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
That's such a dogshit excuse. There are plenty of people, probably 75% of jass users, who don't regularly use TimerUtils.

Don't give numbers on the fly.
Anyway even if it's true, most of people who uses a timer system uses TU, at least when it's about public resources, such as custom spells.

Who says it's for editing? You read the API, start a new map and use a new system. People aren't forever tied to TU just because they understand it.

My point is that you can't safely use TU and mine, or you have to be careful on which functions you are using, you can't mix them, then for old maps it requires edit.
While it should be fair for a personal use, we can't seriously hope everyone will do it correctly.

Maybe, but that's no reason to graveyard your script. You can't say that mag's is "better" than yours.

I'm not saying it's better than mine, just better than the TU on wc3c.net.
Mine is just different, i don't use the same approach in some ways, even if it's still a stack of timer after all.

Nope.. You just replace the hashtable with an array. So it has to be less than what? 8000 timers? I think that won't be a problem. I'd make it with 0 preloaded imo.

The handle id space is not magically consecutive if you create a timer, then other handles, and timers again. There is reason why the red version of TimerUtils preload timers.
I know that Bribe uses a custom version of the red version without any preload, he is just assuming that he will never reach more than 8191/8192 handles created.
It seems reasonable if you avoid any handle id leak, but again hashtables are not that bad.
Also i'm quite sure you can easily break it, like for example you create a timer and an unit on map init (preplaced unit or whatever), the unit is created before the timer, the unit is removed, you create an other timer, it gets the id of the removed unit which is smaller than the offset -> you're screwed.
Now, ofc you could as well just use a constant to avoid that.

NewTimer gets a timer.... you can store all the trash you want on it after you've gotten it.

But a timer callback must have a function which takes and returns nothing as an argument, so you're screwed most of times.
If you still don't get it, try to make an example.

Making TU have a hashtable index is like making a new version of CreateTrigger() that lets you add references to it. Surely it's useful somewhere, but important/worthwhile? Definitely not.

I don't get what you want mean here.
 
Last edited:

Cokemonkey11

Code Reviewer
Level 29
Joined
May 9, 2006
Messages
3,522
Actually, less than 8192 handles on the map, which is very possible D:

But if you instanciate 256 timers on map initialization, those still are included in that 8,192 handle limit. It's not like creating on init has some magic quality that makes it okay.... right?

Don't give numbers on the fly.
Anyway even if it's true, most of people who uses a timer system uses TU, at least when it's about public resources, such as custom spells.

"Most of them who use a timer system" is like what, 25% of the spells in the spells section? Most of those are GUI to begin with.

My point is that you can't safely use TU and mine, or you have to be careful on which functions you are using, you can't mix them, then for old maps it requires edit.
While it should be fair for a personal use, we can't seriously hope everyone will do it correctly.

Why can't you safely use them in parallel..? They have different function names. Maybe I missed something there.

The handle id space is not magically consecutive if you create a timer, then other handles, and timers again. There is reason why the red version of TimerUtils preload timers.
I know that Bribe uses a custom version of the red version without any preload, he is just assuming that he will never reach more than 8191/8192 handles created.
It seems reasonable if you avoid any handle id leak, but again hashtables are not that bad.
Also i'm quite sure you can easily break it, like for example you create a timer and an unit on map init (preplaced unit or whatever), the unit is created before the timer, the unit is removed, you create an other timer, it gets the id of the removed unit which is smaller than the offset -> you're screwed.
Now, ofc you could as well just use a constant to avoid that.

I'm not sure what you mean by that last part.. Read my response to Mag. I'm worried I've misunderstood the point of preloading timers.

But a timer callback must have a function which takes and returns nothing as an argument, so you're screwed most of times.
If you still don't get it, try to make an example.

Okay.

JASS:
library SimpleTimers
    struct SimpleTimers
        private static timer array availableTimers
        private static integer maxAvailable=-1
        
        public static method release takes timer time returns nothing
            call PauseTimer(time)
            set maxAvailable=maxAvailable+1
            set availableTimers[maxAvailable]=time
        endmethod
        
        public static method get takes nothing returns timer
            if maxAvailable==-1 then
                return CreateTimer()
            endif
            set maxAvailable=maxAvailable-1
            return availableTimers[maxAvailable+1]
        endmethod
    endstruct
endlibrary

JASS:
scope thunderClap initializer i
    globals
        private constant integer THUNDERCLAP_CODE='AHtc'
        private constant real POWER=35.
        private constant real RADIUS=300.
        private constant real TRAJECTORY=bj_PI/16.
        private constant real DELAY=1.
        private group grp=CreateGroup()
        private hashtable ht=InitHashtable()
    endglobals
    
    private function a takes nothing returns nothing
        local timer time=GetExpiredTimer()
        local integer id=GetHandleId(time)
        local real direc
        local unit u=LoadUnitHandle(ht,id,0)
        local real x=GetUnitX(u)
        local real y=GetUnitY(u)
        local unit FoG
        call GroupEnumUnitsInRange(grp,GetUnitX(u),GetUnitY(u),RADIUS,null)
        loop
            set FoG=FirstOfGroup(grp)
            exitwhen FoG==null
            if FoG!=u then
                set direc=Atan2(GetUnitY(FoG)-y,GetUnitX(FoG)-x)
                call Knockback3D_add(FoG,POWER,direc,TRAJECTORY)
            endif
            call GroupRemoveUnit(grp,FoG)
        endloop
        call FlushChildHashtable(ht,id)
        call SimpleTimers.release(time)
        set u=null
        set time=null
    endfunction
    
    private function c takes nothing returns boolean
        local timer time
        if GetSpellAbilityId()==THUNDERCLAP_CODE then
            set time=SimpleTimers.get()
            call SaveUnitHandle(ht,GetHandleId(time),0,GetTriggerUnit())
            call TimerStart(time,DELAY,false,function a)
        endif
        return false
    endfunction
    
    private function i takes nothing returns nothing
        local trigger t=CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition(t,Condition(function c))
        set t=null
    endfunction
endscope

See what I'm saying now? Let the client decide when they want to handle data attached to their timers. A timer system should recycle timers, no more, no less. Obviously that's just my opinion.

I don't get what you want mean here.

I mean that making a timer system attached to hashtables is assuming that users always want to store data in the timers. Which yes is typical, but not always necessary. In my opinion it's better to let the client handle the hashtable use.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
But if you instanciate 256 timers on map initialization, those still are included in that 8,192 handle limit. It's not like creating on init has some magic quality that makes it okay.... right?

In the red version of TU, you have to make sure that you will never reach the maximum of timers preloaded, i'm not sure if it will reach the limitop need to be tested, but you can choice 8191 for that matter.
I dislike this version, but the point of it is to use a faster way to link a timer and an integer (struct instance or whatever)

"Most of them who use a timer system" is like what, 25% of the spells in the spells section? Most of those are GUI to begin with.

That doesn't change the fact that where a timer system is used, the mostly one used is TU.

Why can't you safely use them in parallel..? They have different function names. Maybe I missed something there.

You can safely use them in parallel, but you don't have to mix the api on the same timer, and truly we can't seriously hope that no one will mix them, especially beginners.
Plus, then more timers will be created for nothing when you could just use one of them.

I'm not sure what you mean by that last part.. Read my response to Mag. I'm worried I've misunderstood the point of preloading timers.

Well, by preloading timer you make sure the handles ids used by the timers are consecutive, 851962,851963, ...
Then the operation GetHandleId(<timer> - OFFSET) is perfectly safe.
Without preloading, because handles ids are recycled you could have a timer handle id which is smaller than the offset :

<handle id> - OFFSET < 0 : you're screwed.

JASS:
library SimpleTimers
    struct SimpleTimers
        private static timer array availableTimers
        private static integer maxAvailable=-1
        
        public static method release takes timer time returns nothing
            call PauseTimer(time)
            set maxAvailable=maxAvailable+1
            set availableTimers[maxAvailable]=time
        endmethod
        
        public static method get takes nothing returns timer
            if maxAvailable==-1 then
                return CreateTimer()
            endif
            set maxAvailable=maxAvailable-1
            return availableTimers[maxAvailable+1]
        endmethod
    endstruct
endlibrary

JASS:
scope thunderClap initializer i
    globals
        private constant integer THUNDERCLAP_CODE='AHtc'
        private constant real POWER=35.
        private constant real RADIUS=300.
        private constant real TRAJECTORY=bj_PI/16.
        private constant real DELAY=1.
        private group grp=CreateGroup()
        private hashtable ht=InitHashtable()
    endglobals
    
    private function a takes nothing returns nothing
        local timer time=GetExpiredTimer()
        local integer id=GetHandleId(time)
        local real direc
        local unit u=LoadUnitHandle(ht,id,0)
        local real x=GetUnitX(u)
        local real y=GetUnitY(u)
        local unit FoG
        call GroupEnumUnitsInRange(grp,GetUnitX(u),GetUnitY(u),RADIUS,null)
        loop
            set FoG=FirstOfGroup(grp)
            exitwhen FoG==null
            if FoG!=u then
                set direc=Atan2(GetUnitY(FoG)-y,GetUnitX(FoG)-x)
                call Knockback3D_add(FoG,POWER,direc,TRAJECTORY)
            endif
            call GroupRemoveUnit(grp,FoG)
        endloop
        call FlushChildHashtable(ht,id)
        call SimpleTimers.release(time)
        set u=null
        set time=null
    endfunction
    
    private function c takes nothing returns boolean
        local timer time
        if GetSpellAbilityId()==THUNDERCLAP_CODE then
            set time=SimpleTimers.get()
            call SaveUnitHandle(ht,GetHandleId(time),0,GetTriggerUnit())
            call TimerStart(time,DELAY,false,function a)
        endif
        return false
    endfunction
    
    private function i takes nothing returns nothing
        local trigger t=CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition(t,Condition(function c))
        set t=null
    endfunction
endscope

See what I'm saying now? Let the client decide when they want to handle data attached to their timers. A timer system should recycle timers, no more, no less. Obviously that's just my opinion.

I mean that making a timer system attached to hashtables is assuming that users always want to store data in the timers. Which yes is typical, but not always necessary. In my opinion it's better to let the client handle the hashtable use.

You're just reinventing the wheel, it's more error prone and more verbose without any real pro.
If you don't need to attach something to a timer, then you would just create/destroy, in fact it would be even more efficient, the main point of TU is to provide an easy and eventually fast way to link datas with a timer.
Without any way to attach datas with timers, a timer system is pointless, because believe me or not, just use Create/DestroyTimer will be more efficient than using a custom function to get and release timers.
 

Cokemonkey11

Code Reviewer
Level 29
Joined
May 9, 2006
Messages
3,522
That doesn't change the fact that where a timer system is used, the mostly one used is TU.

But that's because TU is the only one they see in the jass section of forums like this.. see what I'm saying?

If I wanted to use a timer system and I looked through the list and saw your well-documented, easy to understand script and I compared it to the following post which, let's just pretend vexorian posted, I'd definitely use yours.

I think you assume people use libraries they are familiar with more than is true.

You can safely use them in parallel, but you don't have to mix the api on the same timer, and truly we can't seriously hope that no one will mix them, especially beginners.
Plus, then more timers will be created for nothing when you could just use one of them.

But that's their fault.. They post in the triggers and scripts section, we say "You instanciated a timer with TU and released it with TimerStack" and they look stupid, but learn from the mistake. Won't happen again.

Well, by preloading timer you make sure the handles ids used by the timers are consecutive, 851962,851963, ...
Then the operation GetHandleId(<timer> - OFFSET) is perfectly safe.
Without preloading, because handles ids are recycled you could have a timer handle id which is smaller than the offset :

<handle id> - OFFSET < 0 : you're screwed.

Ah okay I understand what you meant there now. But what's the point? Why would you want to do that?

You're just reinventing the wheel, it's more error prone and more verbose without any real pro.
If you don't need to attach something to a timer, then you would just create/destroy, in fact it would be even more efficient, the main point of TU is to provide an easy and eventually fast way to link datas with a timer.
Without any way to attach datas with timers, a timer system is pointless, because believe me or not, just use Create/DestroyTimer will be more efficient than using a custom function to get and release timers.

Maybe you're right. Calling a jass function is probably not worth (maybe even slower) than just using CreateTimer() and DestroyTimer(). I guess we'd have to test that one to really know.

Another option would be to increment maxIndex, pause timer, and set timer=stack[index] manually, which would be quite fast, but certainly would never be okay in a public resource.

---


Edit: I've tested it. Turns out the overhead for calling a custom jass function is nearly twice as efficient (can we actually say that?) as using Create/Destroy timer.

JASS:
scope createTimerVsCustomFunc initializer i
    globals
        private constant boolean DOING_CREATES=false //else, doing custom funcs
        private constant real TIMEOUT=1./1000.
        private constant integer COUNT=-2+200
    endglobals
    
    private function none takes nothing returns nothing
    endfunction
    
    private function creates takes nothing returns nothing
        local integer index=0
        loop
            exitwhen index>(COUNT)
            call DestroyTimer(CreateTimer())
            set index=index+1
        endloop
    endfunction
    
    private function customs takes nothing returns nothing
        local integer index=0
        loop
            exitwhen index>(COUNT)
            call none()
            call none()
            set index=index+1
        endloop
    endfunction
    
    private function after takes nothing returns nothing
        static if DOING_CREATES then
            call TimerStart(GetExpiredTimer(),TIMEOUT,true,function creates)
        else
            call TimerStart(GetExpiredTimer(),TIMEOUT,true,function customs)
        endif
    endfunction
    
    private function i takes nothing returns nothing
        local timer time=CreateTimer()
        call TimerStart(time,6.,false,function after)
        set time=null
    endfunction
endscope

At 100,000 executions per second, DestroyTimer(CreateTimer()) spiked to 35 fps and then oscillated between 45 and 55.

At 200,000 per second, none() none() spiked to 47 fps and then oscillated between 55 and 60.

I'll let you decide for yourself what that means, but in my book that's enough to make timer recycling worthwhile.
 
Last edited:
Level 17
Joined
Apr 27, 2008
Messages
2,455
But that's because TU is the only one they see in the jass section of forums like this.. see what I'm saying?

Well if it did matter that much i shouldn't have given up, the fact is no matter you like it or not, TU is a de facto standard.

If I wanted to use a timer system and I looked through the list and saw your well-documented, easy to understand script and I compared it to the following post which, let's just pretend vexorian posted, I'd definitely use yours.

I think that TU is documented enough, yes the static ifs seem eyesore and cumbersome for a vJass beginner, but when it's converted in jass, it's not.
Now, use Mag's version of TU is much better, because of the fix.
I think that Mag version should be ungraveyarded and explained why this version is better.

I think you assume people use libraries they are familiar with more than is true.

Yep, that's why it doesn't worth it.
But well, instead of the graveyard, maybe there should be a section for scripts that we could use in a personal resource, and not in a public one.

But that's their fault.. They post in the triggers and scripts section, we say "You instanciated a timer with TU and released it with TimerStack" and they look stupid, but learn from the mistake. Won't happen again.

I don't believe in humans that much, this "error" will pop up many times.
And again if you use TU and mine, you will "spam" timers for nothing.

Ah okay I understand what you meant there now. But what's the point? Why would you want to do that?

It's just to make the offset as the first handle id on an integer variable (first timer created), then you're sure that you will be able to use 8191 timers or less.
You don't have to define a constant.
Plus, it keeps the array size as low as possible (theorically use the array should be faster then)


Maybe you're right. Calling a jass function is probably not worth (maybe even slower) than just using CreateTimer() and DestroyTimer(). I guess we'd have to test that one to really know.

Another option would be to increment maxIndex, pause timer, and set timer=stack[index] manually, which would be quite fast, but certainly would never be okay in a public resource.

---


Edit: I've tested it. Turns out the overhead for calling a custom jass function is nearly twice as efficient (can we actually say that?) as using Create/Destroy timer.

JASS:
scope createTimerVsCustomFunc initializer i
    globals
        private constant boolean DOING_CREATES=false //else, doing custom funcs
        private constant real TIMEOUT=1./1000.
        private constant integer COUNT=-2+200
    endglobals
    
    private function none takes nothing returns nothing
    endfunction
    
    private function creates takes nothing returns nothing
        local integer index=0
        loop
            exitwhen index>(COUNT)
            call DestroyTimer(CreateTimer())
            set index=index+1
        endloop
    endfunction
    
    private function customs takes nothing returns nothing
        local integer index=0
        loop
            exitwhen index>(COUNT)
            call none()
            call none()
            set index=index+1
        endloop
    endfunction
    
    private function after takes nothing returns nothing
        static if DOING_CREATES then
            call TimerStart(GetExpiredTimer(),TIMEOUT,true,function creates)
        else
            call TimerStart(GetExpiredTimer(),TIMEOUT,true,function customs)
        endif
    endfunction
    
    private function i takes nothing returns nothing
        local timer time=CreateTimer()
        call TimerStart(time,6.,false,function after)
        set time=null
    endfunction
endscope

At 100,000 executions per second, DestroyTimer(CreateTimer()) spiked to 35 fps and then oscillated between 45 and 55.

At 200,000 per second, none() none() spiked to 47 fps and then oscillated between 55 and 60.

I'll let you decide for yourself what that means, but in my book that's enough to make timer recycling worthwhile.

Your benchmark is totally flawed, because your custom function is empty.
Here is valid one in attachments.
Use the optimized maps, because the size name of variables, functions does matter.

Result : 25 fps for Create/Destroy and freez for timer recycling.

Note that's even an unrealistic case because here variable and function name are 1 character length where in a real optimized map it should be 2 or even 3.
It means that in a real map timer recycling would be even slower than it is here.

I'll let you decide for yourself what that means, but in my book that's clearly not enough to make timer recycling worthwhile.
 

Attachments

  • benchmark timer natives.w3m
    12.2 KB · Views: 96
  • benchmark timer recycling.w3m
    12.5 KB · Views: 60
  • benchmark timer natives[opt].w3m
    12.4 KB · Views: 80
  • benchmark timer recycling[opt].w3m
    12.4 KB · Views: 55
Level 17
Joined
Apr 27, 2008
Messages
2,455
Well, i've realized that i've forgotten to pause the timer on the native function benchmark (i've never tested if a timer still can expire when it has been destroyed or if it's a bug from the past who got be fixed in newer patchs), also i don't set it to null since i used the same global variable every time.
But go ahead and add this stuff i'm quite sure that the native way will still beat the recycling, jass is slowly interpreted after all.
If we didn't have to link datas and timers, recycling would be totally pointless.
 

Cokemonkey11

Code Reviewer
Level 29
Joined
May 9, 2006
Messages
3,522
Troll-Brain, I've checked out your test script. That's pretty impressive.

Both maps started for me at 60 fps; the recycling one slowly dropped until it hovered at about 15, and the native dropped (more slowly) to about 35.

I guess all I've proved is that the average cost of Create/Destroy Timer is less than that of calling a function in jass, which basically means that recycling timers is better than TimerUtils itself, but not as good as CreateTimer() -> DestoryTimer().
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
That's why a timer recycling without any way to link datas is pointless, just like your newest submission does.

TimerUtils was never to make get/release timers faster than Create/Destroy/Timer but to provide an easy and eventually fast way to link datas with timers.
 

Cokemonkey11

Code Reviewer
Level 29
Joined
May 9, 2006
Messages
3,522
That's why a timer recycling without any way to link datas is pointless, just like your newest submission does.

Yep, I've made a note to have it graveyarded. I'm still so surprised that an array read can be that expensive.

TimerUtils was never to make get/release timers faster than Create/Destroy/Timer but to provide an easy and eventually fast way to link datas with timers.

I understand that now, which makes me 100% sure that it's a useless utility. Hashtables are just so simple on their own, especially when a native is given for them. It's not like someone had to script the algorithm for hashing in jass. Whatever though, to each their own.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
I'm still so surprised that an array read can be that expensive.

There is keyword in this sentence :

Jass is a slowly interpreted language.

Now even when you don't have to link data, sometimes recycling is worthwhile, like dummies units, since creating unit is the most expensive thing in jass.

I understand that now, which makes me 100% sure that it's a useless utility. Hashtables are just so simple on their own, especially when a native is given for them. It's not like someone had to script the algorithm for hashing in jass. Whatever though, to each their own.

It's totally unfair and lame to say that.
For humans, errors are pretty common, and less verbosity/code abstraction is almost always good.

First, it's more verbose and then more error prone and annoying to write. It's very easy to reverse the order of the hashtable arguments, just as an example.
Second, if you don't use TU or whatever you will either have to use a whole hashtable or Table (ofc if you don't already use one).
Third, if you care about efficiency that much it makes sense to choice the speed on getting data linked to a timer over all the other timer operations, especially if it's a periodic one, and then the red version of TU is for you, or something similar which uses an array.
Fourth, TU has debug stuff which is always good, double free or whatever.
Last, it eventually fix a bug about destroyed expiring timers, sure you can still use it yourself, but remember you're just an human.

Also, again hahstables are not that slow, last time i benchmarked it an hashtable read is only about 4 times slower than an array, and when it's about writing it's about 20 times.

If you're still not convinced, then, in the same manner, maybe you should go for struct extends array all the time.
 

Cokemonkey11

Code Reviewer
Level 29
Joined
May 9, 2006
Messages
3,522
There is keyword in this sentence :

Jass is a slowly interpreted language.

Of course I understand that without it being forced down my throat. I have plenty of experience with interpreted versus compiled code.

To be fair though, jass really isn't that bad. For a 10+ year old game, we sure abuse the shit out of it and make some cool stuff.

Now even when you don't have to link data, sometimes recycling is worthwhile, like dummies units, since creating unit is the most expensive thing in jass.

Yes of course. I guess the obvious thing that I failed to notice was that a timer in jass isn't anything more than a timer in compiled code, while obviously a unit is a more complex object.

It's totally unfair and lame to say that.

I respect your opinion, but disagree.

For humans, errors are pretty common, and less verbosity/code abstraction is almost always good.

Unless you're talking about a "slowly interpreted language", where inlining code is a good thing 9 times out of 10.

Anyway, I'm really glad TU works for some people, but for me, it's pretty pointless. But that's a discussion for another thread, we've blabbered on about this long enough I guess.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Unless you're talking about a "slowly interpreted language", where inlining code is a good thing 9 times out of 10.

You rarely see any difference in game by inlining it or not in jass, since after all we are mostly doing Event driven programming.
Code abstraction seems a better reason.
Hell, even GUI is enough most of times.

Anyway, I'm really glad TU works for some people, but for me, it's pretty pointless. But that's a discussion for another thread, we've blabbered on about this long enough I guess.

Yes it's enough. It's fair if you personally consider it useless, but it was just for highlight that's just an opinion (quite lame for me, but that's my opinion, even if i've given reasons)
 
Top