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

[JASS] which is fastest?

Status
Not open for further replies.
Level 11
Joined
Apr 6, 2008
Messages
760
this been bugging me for quite a while now can figure out which is the best way

e.g 1
JASS:
local real x
local real y
local real ux
local real uy
local real angle = //blahblahblah

set x = GetUnitX(c)
set y = GetUnitY(c)
set ux = (x + 100 * Cos(angle * bj_DEGTORAD))
set uy = (y + 100 * Sin(angle * bj_DEGTORAD))

set dum = CreateUnit(GetOwningPlayer(c),'h000',ux, uy, angle)

e.g 2
JASS:
set dum = CreateUnit(GetOwningPlayer(c),'h000',(GetUnitX(c) + 100 * Cos(angle * bj_DEGTORAD)),(GetUnitY(c) + 100 * Sin(angle * bj_DEGTORAD)), angle)

what i really wanna know is it faster to save stuff in to a var(not all stuff ofc) or "set it" on the the "call"(like in e.g 2)? thx for your time
 
Last edited:
Level 17
Joined
Apr 27, 2008
Messages
2,455
the second is the fastest because declare/remove a local take some time.
and set variable as well but so few
and here you don't need any variable.
But four your mental sanity and make your code readeable and easy to edit you should use the first, or why not use globals instead :wink:

PS : for few reading/writing of variables , globals is the best choice, but work with local is faster, so it depends the number of the read/write of the same variable, and of course for the MUI needing or not
 
Level 11
Joined
Apr 6, 2008
Messages
760
i tried out using e.g2 but stuff got really inaccurate (20degree or more off from where i targeted), i would start using Vjass by now but cant get the darn program to work (its not getting moded)

JASS:
local unit c
local unit d
local real angle

set c = GetTriggerUnit()
set angle = Atan2((GetLocationY(GetSpellTargetLoc())-GetUnitY(c)),(GetLocationX(GetSpellTargetLoc())-GetUnitX(c)))*57.29583
set dum = CreateUnit(GetOwningPlayer(c),OrbDummyId(), (GetUnitX(c) + 100 * Cos(angle * bj_DEGTORAD)), (GetUnitY(c) + 100 * Sin(angle * bj_DEGTORAD)), angle)

this is how it looked before and its 100% accurate

JASS:
local unit c
local unit dum
local real x 
local real y
local real tx
local real ty
  
set c = GetTriggerUnit()
set tx = GetLocationX(GetSpellTargetLoc())
set ty = GetLocationY(GetSpellTargetLoc())
set x = GetUnitX(c)
set y = GetUnitY(c)
set angle = Atan2((ty-y),(tx-x))*57.29583
set dum = CreateUnit(GetOwningPlayer(c),OrbDummyId(), (x + 100 * Cos(angle * bj_DEGTORAD)), (y + 100 * Sin(angle * bj_DEGTORAD)), angle)
 
Well, configureability and efficiency are different stuff.

Configureability is like the stuff you use, and it allows you to configure options easily. Efficiency, is a different thing where speed matters. User efficiency is configureability.


So yes, it is what you prefer. You can probably just optimize it with Vexorian's map Optimizer though, so I think it is best for configurable values. Also, your code can be optimized (directly intialized)
JASS:
local unit c = GetTriggerUnit()
local real x = GetUnitX(c)
local real y = GetUnitY(c)
local real tx = GetLocationX(GetSpellTargetLoc())
local real ty = GetLocationY(GetSpellTargetLoc())
local real angle = Atan2(ty-y,tx-x)*57.29583
local unit dum = CreateUnit(GetOwningPlayer(c),OrbDummyId(), (x + 100 * Cos(angle * bj_DEGTORAD)), (y + 100 * Sin(angle * bj_DEGTORAD)), angle)

Kind of like that ;)
 
Level 11
Joined
Feb 18, 2004
Messages
394
the fewest number of operations is always the fastest. A function call is very expensive time-wise. The only time you have to worry about efficiency is when doing complex things like maze generation, where you want a low-complexity algorithm and low execution time, or things that are done very often. (more than 20 times a second.)

If you are doing something that needs optimal code, then avoid using user-land functions as much as possible. Also avoid calling natives if it is feasible to do so. (Sometimes, the workaround to not calling a function will take more time than just calling a function.) If you require the same complex operation performed twice, store the result in a variable. If the operation is simplistic enough, such as var + 1 or var * 5 then don't worry about it.

Optimization makes code less readable and thus less maintainable. Optimize only what needs to be optimized and only to the extent it needs to be optimized. As for your example in the first post, I would go for something in the middle with:
JASS:
local real angle = //blahblahblah
local real x
local real y

set x = GetUnitX(c) + 100 * Cos(angle * bj_DEGTORAD)
set y = GetUnitY(c) + 100 * Sin(angle * bj_DEGTORAD)

set dum = CreateUnit(GetOwningPlayer(c), 'h000', x, y, angle)

As a side note, it takes a large amount of time to allocate and deallocate handle-types like locations. Do not use them. And, if you must use GetLocationZ(), use a single global location that you move to the desired spot just prior to using GetLocationZ(). GetSpellTargetLoc() is also a problem, but not much of one.
 
Level 5
Joined
Oct 27, 2007
Messages
158
then i must miss understood it or something...

Well obviously locals aren't initially set to 0, otherwise you wouldn't get those nice red text error messages when trying to use non initialized locals, if you use JNG pack.

So doing this.....

JASS:
function blabla takes nothing returns nothing
    local unit u

    set u = GetTriggerUnit()
    // blabla
    set u = null
endfunction
Or this.....

JASS:
function blabla takes nothing returns nothing
    local unit u = GetTriggerUnit()

    // blabla
    set u = null
endfunction
Will make no difference. You know why it doesn't make any difference if you look at how the disassembled code would look like. A stack frame is made that contains all locals. Then those locals need to be set one way or the other, and you can only set the locals after the stack frame is created. You use exactly the same function (GetTriggerUnit()) to initialize the local, so in terms of speed there is no difference.

Code:
push ebp
mov ebp, esp // ebp holds reference to local stack frame
sub esp, 4 // one local, 4 byte handle placeholder to unit
call blizzard_function // calls the function that gets trigger unit, returns handle in eax
mov dword ptr [ebp - 4], eax // handle to trigger unit is put in local handle type placeholder
// rest of the blabla
mov dword ptr [ebp - 4], 0 // clean up
add esp, 4 // Destroy stack frame and there by locals
pop ebp
ret // return from function
I do know that some compilers will fill a local stack frame with zero's to begin with, to prevent using non initialized locals. That's not the case here. Even then there would be no difference in speed, because the initial initialization to zero would happen even though you assign a value to a local or not.

ps.

Just to make sure this isn't misunderstood....
I'm not saying that the same goes for something like this.

JASS:
function blabla takes nothing returns integer
    local unit u = GetTriggerUnit()
    local integer id = GetUnitTypeId(u)

    // blabla
    set u = null
    return id
endfunction

JASS:
function blabla takes nothing returns integer
     local unit u = GetTriggerUnit()
 
     // blabla
     set u = null
    return GetUnitTypeId(u)
 endfunction

The latter is obviously faster. Not because there is one less local but because the former needs more operations to return the unit type than the latter.
 
Level 19
Joined
Aug 24, 2007
Messages
2,888
if you are gonna use a value returning function one time
use it when you need to

if you are gonna use same value returning function many times
local it first and use localled variable in actions

and
in some function << slower than bellow
local integer array i
set i[1] = 0
return i[1]

in some function << faster
local integer i
set i = 0
return i
 
Level 5
Joined
Oct 27, 2007
Messages
158
if you are gonna use a value returning function one time
use it when you need to

if you are gonna use same value returning function many times
local it first and use localled variable in actions


Are you saying that when you use a function that returns something only once, set the local variables whenever you need to?
And when you use a function that returns something a lot, you set the locals where you declare them?

If so, then why are you doing that?

and
in some function << slower than bellow
local integer array i
set i[1] = 0
return i[1]

in some function << faster
local integer i
set i = 0
return i
You're comparing data retrieval from a single integer variable to that of an integer array. It's very obvious that array value retrieval is slower than retrieving a single non array value.
 
Status
Not open for further replies.
Top