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

Efficiency questions

Status
Not open for further replies.
Level 9
Joined
May 27, 2006
Messages
498
Right now i am working on a Heroes 3-like combat system, and since i also want to improve my efficient-coding skills, i have a few questions regarding that matter:

1. Constant variables or constant functions? I know they are used in defining configuration values that don't change throughout the game, but which method is better to use? Or do one perform better than the other in some specific tasks?

2. FirstOfGroup loops, unit comparison loops. I've heard they are slow and inefficient, but i can't think of a loop which would accomplish the same goal, but would be more efficient. Should i compare handle id's instead, or put units in a global array and then loop through its' indexes?

3. Struct members vs. GetUnitAbilityLevel(). The reason i'm asking this question is because each unit has a struct instance associated with it, and this struct has approx. 15 members, therefore i'm becoming anxious of adding even more members to it (tho number of these structs will almost never exceed 14). Since some of these members are booleans describing the units' state, i thought about replacing them with abilities and simply checking whether the unit has a certain ability or not. Should i be concerned about those structs and use abilities, or are booleans a better option?

4. Dynamically creating and destroying a trigger. I have a function which looks like that:
JASS:
function DestinationDo takes nothing returns nothing
    set HCS_dr = true
endfunction

function SomeFunc takes nothing returns nothing
    // (...)
    set HCDestinationTrig = CreateTrigger()
    call TriggerRegisterUnitInRange(HCDestinationTrig, GetOrderTargetUnit(), DEST_RANGE(), e)
    call TriggerAddAction(HCDestinationTrig, function DestinationDo)
    // DestinationDo is meant to run only when a unit comes within range of a very
    // specific unit, therefore the trigger must have only one event registered.
    loop
        exitwhen HCS_dr == true
        call TriggerSleepAction(0)
    endloop

    set HCS_dr = false
    call DestroyTrigger(HCDestinationTrig)
    call DestroyBoolExpr(e)
    set HCDestinationTrig = null
    set e = null
    // (...)
endfunction
Should this kind of action be avoided, or is it reasonable in this case? I'm concerned because i've read that creating and destroying triggers within short periods of time is generally bad. This function runs once per approx. 5-10 seconds, so it's not that rapid, also it has no intersections with other functions.

5. Reversing structs. I have a struct, and a unit that is its' member. Now i know have the unit variable, but i need to retrieve to what struct instance it belongs. Is there another way to accomplish that, other than looping through all struct instances and comparing their members to the variable?
 
Level 9
Joined
May 27, 2006
Messages
498
Thanks for replies
watermelon_1234 said:
1. I would say use functions since if you have too many global variables, it would become slower to use them.
How many? Right now i have over 20 constant functions/globals, but i anticipate there are going to be over 100, since i still have to create spells etc.

Axarion said:
4. Don't destroy triggers. It could bug your whole map.
Damn, that's bad, since i can't have two triggers of that sort active at one time, it would screw up entire movement system i made. Should i disable them instead? Would they leak?
Oh well, nvm, i guess i'll just create a separate trigger for every unit i need and use a trigger array to reach the trigger i need at the time.

Axarion said:
5. Set the struct instance to the unituserdata if not used or use an indexer system.
I do use an indexer system of some sort, basically it's a 2d array, so indexes are arranged in a predictable order. But honestly, i completely forgot about UnitUserData, thanks for reminding me about it, i guess it's a better option for me.


One more question. Is there a difference in performance between unit comparison and other kinds of comparisons? Like: if unit == GetTriggerUnit() then and if integer > 10 then. Would integer comparison be faster in that case, or is there no difference at all?
 
Level 11
Joined
Sep 30, 2009
Messages
697
watermelon_1234 said:
1. I would say use functions since if you have too many global variables, it would become slower to use them.
Whats better a thousand functions or a thousand globals? I don't know it but i think globals should be faster.

raft_pl said:
Damn, that's bad, since i can't have two triggers of that sort active at one time, it would screw up entire movement system i made. Should i disable them instead? Would they leak?
Oh well, nvm, i guess i'll just create a separate trigger for every unit i need and use a trigger array to reach the trigger i need at the time.
I think pausing would be ok.

raft_pl said:
I do use an indexer system of some sort, basically it's a 2d array, so indexes are arranged in a predictable order. But honestly, i completely forgot about UnitUserData, thanks for reminding me about it, i guess it's a better option for me.
With indexer system i meant something like AutoIndex or UnitIndexer, which add an unique id for arrays to units via UnitUserData

raft_pl said:
One more question. Is there a difference in performance between unit comparison and other kinds of comparisons? Like: if unit == GetTriggerUnit() then and if integer > 10 then. Would integer comparison be faster in that case, or is there no difference at all?
I don't think it would matter that hard if its not spammed a thousand times per thread.
 
Level 9
Joined
May 27, 2006
Messages
498
Axarion said:
With indexer system i meant something like AutoIndex or UnitIndexer, which add an unique id for arrays to units via UnitUserData
Yeah, i know what indexing systems are, but in my system i don't need such overwriting-security. Array indexes are arranged at the map initialization, and they never change their contents.

Well, thanks for help anyway. Regarding 1., i guess i'll just follow the logic i've been following all the time: use constant functions for ID's, and globals for config.
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
Whats better a thousand functions or a thousand globals? I don't know it but i think globals should be faster.
That's not a really good comparison considering how one constant function can do this
JASS:
constant function Damage takes integer lvl, integer otherStat returns real
    return 100. + 2*lvl + 5*otherStat
endfunction
whereas you would need at least 3 globals to express that if you wanted it to be easy to customize.

However, this is really hypothetical so I don't think we should talk more about this unless we have evidence to back up our claims. I do think you should use globals though if you're only returning an independent constant value.
 
Status
Not open for further replies.
Top