• 🏆 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] Operation limits ?

Status
Not open for further replies.

Ardenian

A

Ardenian

I faced several time the problem that a a very long and complex Jass script or a loop that could possibly run pseudo-infinite times just stopped working.

I recently heard the term 'operation limit', stating a function can perform only a limited amout of lines or something.
So, how do I concept a script to avoid this ?

Example:
JASS:
loop
exitwhen i > 100
    loop
    exitwhen i2 > 100
    
       loop 
       exitwhen i3 > 100
           set i3 = i 3 + 1
       endloop
    set i2 = i2 + 1
    endloop
set i = i + 1
endloop

Could I reduce the operations when externalizing one loop,
so I would have to call the function for every i from a GUI trigger, for example ?

What is the general concept to avoid reaching the operation limit, structure-wise ?
 
Level 17
Joined
Dec 11, 2014
Messages
2,004
Operation limit is a term used when the loop reaches 8191 times running (in my computer, I don't know why it is 1891). After lagging like hell, you'll face a "Thread Crash"; another term that means your calling trigger will stop.


An infinite loop is like this:
  • I will run forever, no operation limit
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Trigger - Run (This trigger) (ignoring conditions)
Using that technique, you can use boolexpr for a function so you'd have an artificial exitwhen.
 

Ardenian

A

Ardenian

Hm, I am not sure whether that is my problem.
My function just stops looping at a certain point, without any lag. I had different counts for the loop, 2707 and 3600, depending on line count and function calls.

Another function running infinitly does lag, so I think that are different issues.
However, I cannot provide a script, it is too complex.

Another example is unit creation. If you order a trigger to run and create units every 64 x and every 64 y, e.g., then the creation stops after a certain amount of units ( haven't tested that particular environment, but that's how it feels)
 
Level 17
Joined
Dec 11, 2014
Messages
2,004
The Warcraft III engine was created 13 years ago! Warcraft III has the same age as I have, what do you expect? The engine is pretty weak when it comes to large number of handles (or loops). Units (handles in general, unused handles are called leaks) take 4kb of memory each and when you have 10000 units then you will have lag (depends on your computer).

Not providing the script because it's too "complex"? Hmmm... Showing it is much better than not showing it.

Also, for your script, try using debug messages. They check for Thread Crashes.

JASS:
call BJDebugMsg("Function is going to run")
call MahScript()
call BJDebugMsg("No thread crash")

If you didn't see "No thread crash", then check for thread crashes.
 
Level 22
Joined
Feb 6, 2014
Messages
2,466
It's not reaching OP limit. You're not resetting the values of i3, i2 so the internal loops only run once in your case. I think what you want to achieve is this:
JASS:
set i = 0
loop
exitwhen i > 100
    set i2 = 0
    loop
    exitwhen i2 > 100
       set i3 = 0
       loop 
       exitwhen i3 > 100
           //Actions here
           set i3 = i 3 + 1
       endloop
    set i2 = i2 + 1
    endloop
set i = i + 1
endloop
Anyways, ^that could reach OP limit pretty quick. Common solutions to avoid OP limit is to run the code in a different thread. Example, your code you be translated to something like this
JASS:
globals
    private trigger loop2 = CreateTrigger()
    private trigger loop3 = CreateTrigger()
    private integer i
    private integer i2
    private integer i3
endglobals

function SomeFunction takes nothing returns nothing
    set i = 0
    loop
        exitwhen i > 100
        call TriggerEvaluate(loop2)
        set i = i + 1
    endloop
endfunction

function Loop2 takes nothing returns boolean
    set i2 = 0
    loop
        exitwhen i2 > 0
        call TriggerEvaluate(loop3)
        set i2 = i2 + 1
    endloop
    return false
endfunction

function Loop3 takes nothing returns boolean
    set i3 = 0
    loop
        exitwhen i3 > 0
        //Actions here
        set i3 = i3 + 1
    endloop
    return false
endfunction

//some Init function
function Init_blah takes nothing returns nothing
    call TriggerAddCondition(loop2, Condition(function Loop2))
    call TriggerAddCondition(loop3, Condition(function Loop3))
endfunction

But note that executing in a different thread will require more CPU resources. It's sole purpose in my example is to avoid the OP limit.
 
Last edited:
Level 12
Joined
Mar 13, 2012
Messages
1,121
Operation limit is 300000 ops. This post gives a good overview.

For normal mapmaking purposes it's useless overpolishing and potentially non-future-proof but if you are really going for maximum efficiency you have to estimate/find out via debugging to adjust your function so that it runs just below the opcode limit. Then fire it up repeatedly from the outside via a TriggerEvaluate or ExecuteFunc("funcName") so that it runs in a new thread again and again.
 

Ardenian

A

Ardenian

Thank you guys, your posts pretty much clean my questions up.

Would this be a correct solution for my example, too ?

JASS:
function Loop3 takes data2 returns data3
    //(...)
    return data3
endfunction

function Loop2 takes data returns data4
    //(...)
    call Loop3(<data2>)
    //(...)
endfunction

function Loop1 takes nothing returns nothing
    //(...)
    call Loop2(<data>)
    //(...)
endfunction

Or would this be within the same thread ? / Are different functions different threads ?
Or is one thread everything after an initial function call ?

Whats is 'call TriggerEvaluate(loop3)' in Flux's example, what does it do and how to use it appropriately ?
I don't quite get the structure of that example and how it works.
 
Level 22
Joined
Feb 6, 2014
Messages
2,466
Thank you guys, your posts pretty much clean my questions up.

Would this be a correct solution for my example, too ?

JASS:
function Loop3 takes data2 returns data3
    //(...)
    return data3
endfunction

function Loop2 takes data returns data4
    //(...)
    call Loop3(<data2>)
    //(...)
endfunction

function Loop1 takes nothing returns nothing
    //(...)
    call Loop2(<data>)
    //(...)
endfunction

Or would this be within the same thread ? / Are different functions different threads ?
Or is one thread everything after an initial function call ?
Same thread.

Whats is 'call TriggerEvaluate(loop3)' in Flux's example, what does it do and how to use it appropriately ?
I don't quite get the structure of that example and how it works.

It executes the conditions of trigger loop3 thus it will run function Loop3

But Bribe's solutions is much cleaner so just follow that.
 
Status
Not open for further replies.
Top