HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Function Speed - Clear Explanation?

11-11-2007, 03:43 AM#1
MrApples
I've heard lots of different things on function speeds... so I thought I'd ask about it generally in one topic. Sorry if this was done before.
  • How fast is a BJ, in relation to a native?
  • If custom funcs are different from BJs, how fast are they in relation?
  • What is actually affected, the calling, or the actual processing speed of the function? ( If the function were really long, would it matter)
  • Calling functions in function in function, are they much slower?
So... based on all that, would trigger BEAR, or trigger KOALA be faster?
Code:
function walrus takes stuff returns stuff
    calls SomeFunction(native)
    calls AnotherFunction(native)
    calls YAFunction(native)
endfunction

Trigger BEAR
    set variable = walrus(variable)

Trigger KOALA
    calls SomeFunction(BJ)
    calls AnotherFunction(BJ)
    calls YAFunction(BJ)

I've also been told triggers are 2nd to natives in speed.
11-11-2007, 03:51 AM#2
Malf
Fuction calls in JASS are slow. That's why BJ's are slow, because here's a BJ(no I'm not giving you a blowjob):
Collapse JASS:
function CreateItemLoc takes integer itemid, real x, real y returns nothing
 set bj_lastCreatedItem = CreateItem(itemid,x,y)
endfunction

Most BJ's are like that, they look stupid.

And how the hell can a trigger be almost as fast as a native? The trigger is just a handle that calls funcs.
11-11-2007, 03:58 AM#3
CaptainPicard
As with all code, function calls take time and are fairly expensive operations. Most optimizing compilers will scout around your code for small functions and in-line them, that is, put the operations of that function directly in the operations of another. In-lining is what you have done in function KOALA, which would be faster than function BEAR (whaddayaknow, no optimizations are done by the WC3 JASS script editor).

This is primarily why GUI is often much slower than custom script: every time you do an if-then in GUI, the editor writes a separate function with a name never intended to be read by humans to evaluate the conditional. Simply doing this on the if-then line saves a function call as well as a lot of nasty code.

These function calls are indeed expensive operations, particularly in JASS, and to conclude this is also the reason that BJ functions are slower than natives. Mostly, what BJ functions do is some very minimal pre-processing of data so that it can be cleanly fed into a native function, without making the JASS compiler barf during a map save or producing some weird result during gameplay. So, if you understand the restrictions on the data that should be fed to a native, enforce them yourself and save an extra function call.
11-11-2007, 04:37 AM#4
MrApples
The KOALA vs BEAR is actually a question on BJ's. KOALA calls 3 BJ's, while BEAR calls a function which calls 3 natives.

How about the actual processing speed(aside from the calling)?

And yea someone did tell me triggers beat custom functions, and he knows his stuff too.. Like setting globals for return and take and then executing a trigger would be much faster than having a custom func do the same thing(if they were long enough).
11-11-2007, 11:16 PM#5
Jazradel
If you want to test:
Quote:
Originally Posted by SFilip;573367
A somewhat short version...
Get grimoire (or newgen), make sure japi and nativepack are loaded in your ongameload.lua, create a new map, import the custom common.j (found in the japi directory of newgen/grimoire) and use something like this:
Collapse JASS:
function dotest takes nothing returns nothing
    local integer n = 0
    local integer swatch = StopWatchCreate()
    loop
        exitwhen n == 1000
        // do whatever you want to test here
        set n = n + 1
    endloop
    call BJDebugMsg(R2S(StopWatchMark(swatch)*1000.))
    call StopWatchDestroy(swatch)
endfunction
Now use startwar3 or war3win in grim/newgen directory to start the game, load your map and you should get the output in µs (1/10^6 seconds).
Of course it's recommended that you run this a couple of times (I usually get the average out of 100 runs) for more precise results. Also note that this can't get you the exact time something takes to run, should be used mainly for comparing.
And these are some results:
Quote:
Originally Posted by PipeDream
Measurements on my machine, an Athlon 64 4400+, 1stddev error bars are all at +-5us.
Calling empty native: 29us
Calling sin: 30us
Calling sqrt: 30us
Multiplying two numbers: 40us
Setting a global real: 20us
Calling empty JASS function: 18us
So, a BJ is 18us slower than running the natives directly.
11-12-2007, 03:40 PM#6
Captain Griffen
Jazradel, BJs are slower than that, and it's more complex than that. Stuff passed takes processing as well, and longer named functions take longer.
11-12-2007, 04:07 PM#7
cohadar
In my opinion only BJ's with one line of code inside should be inlined.
11-12-2007, 07:42 PM#8
MaD[Lion]
Function calls are just fine, if u dont intend to call them in a small periode.
I inline everything in small periodic triggers. but for things tat doesnt happen too often, i use BJ too ^^ Cus some BJ are nice. only those ugly BJ tat just call 1 native is ugly
11-12-2007, 08:55 PM#9
darkwulfv
A lot of the times the differences in speed are so insignificant (what's .00000000000003 second difference in most spells?) that it almost doesn't matter. In major systems which run insane amounts of times with insane stuff, it makes a difference. But if you're coding a simple spell, it doesn't make a HUGE difference.

Now, that's not saying you should cram your code with BJ's and slow shit. Obviously, keep it optimized. But unless what you're doing is insane and every 1/100000 of a second matters (for whatever reason that may be), I wouldn't make too big of a deal about it.