Execution Speed. If vs =

Discussions about Coding and Scripting
Post Reply
MrLoathsome
Inhuman
Posts: 958
Joined: Wed Mar 31, 2010 9:02 pm
Personal rank: I am quite rank.
Location: MrLoathsome fell out of the world!

Execution Speed. If vs =

Post by MrLoathsome »

Consider this line of code in a Tick() function:

Code: Select all

		if (!bUseInv) ThePlayer.SelectedItem = None;
If it were changed to:

Code: Select all

		if ((ThePlayer.SelectedItem != None) && (!bUseInv)) ThePlayer.SelectedItem = None;
Which would execute faster? Is the extra condition in the "if" faster than just assigning SelectedItem to none?
blarg
Higor
Godlike
Posts: 1866
Joined: Sun Mar 04, 2012 6:47 pm

Re: Execution Speed. If vs =

Post by Higor »

The cost of a script opcode is about 5-25 times as much as a c++ counterpart.
The bigger the code, the faster the c++ counterpart (due to c++ code running calling in pipelined CPU's)
Let's see, if i remember well...


On your original case:
EX_JumpIfNot, (*)
Not_PreBool, [!]
EX_BoolVariable (or EX_LocalVariable)
-> (*) If condition evaluates to false, jumps beyond of the code inside the if () {...} brackets
EX_Let, [=]
EX_Context,
EX_LocalVariable,
EX_InstanceVariable,
EX_NoObject [None]
While the code is smaller, it'll always execute the EX_Let operation if bUseInv is always False.
UnrealScript opcodes executed based on bUseInv value (all of them in lower GNatives, no lookup or double byte parsing needed):
- True -> 8
- False -> 3
EX_JumpIfNot, (*)
AndAnd_BoolBool,
EX_Skip, (**)
NotEqual_ObjectObject, [!=]
EX_Context,
EX_LocalVariable,
EX_InstanceVariable,
EX_NoObject, [None]
-> (**) Skip may cause a jump outside of the full conditional here, followed by offset specified by EX_JumpIfNot
Not_PreBool, [!]
EX_BoolVariable (or EX_LocalVariable)
-> (**) Skip destination here if first condition fails.
-> (*) If full condition evaluates to false, due to either side of &&, jumps beyond of the code inside the if () {...} brackets
EX_Let, [=]
EX_Context,
EX_LocalVariable,
EX_InstanceVariable,
EX_NoObject [None]
While the code is bigger, it'll always execute the NotEqual_ObjectObject operation inside a && skip... regardless of the bUseInv value.
On a single cleanup event:
- All opcodes are executed -> 15
UnrealScript opcodes executed based on bUseInv value, post cleanup (all of them in lower GNatives, no lookup or double byte parsing needed):
- True -> 8 (because of previous cleanup, SelectedItem equals none)
- False (selecteditem=none) -> 8
- False (selecteditem!=none) -> 10

Take your pick.
========================================================
A reasonably fast implementation would be:

Code: Select all

native final operator(10) Object =! (out Object ObjVariable, bool bClearIfFalse);
Usage:
ThePlayer.SelectedItem =! bUseInv; //The operator returns the final output as well, if you want to use it within other conditionals
With c++ code doing something like:

Code: Select all

void UXC_CoreStatics::execEqualNot_ObjectBool( FFrame &Stack, RESULT_DECL)
{
   P_GET_OBJ_REF(ObjVariable);
   P_GET_BOOL(bClearIfFalse);
//P_FINISH; //Not needed because it's an operator
   *(UObject**)Result = bClearIfFalse ? ObjVariable : NULL;
}
In this case we'd have:
EX_FinalFunctionCall (because operator isn't a GNative)
execEqualNot_ObjectBool [=!]
EX_Context
EX_LocalVariable
EX_InstanceVariable
EX_BoolVariable (or EX_LocalVariable)
Always having 6 opcodes, regardless of the player's selected item or the bUseInv value.
User avatar
sektor2111
Godlike
Posts: 6410
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Execution Speed. If vs =

Post by sektor2111 »

Isn't more simple to clock it using XC_Core for more relevant results ?
User avatar
Wormbo
Adept
Posts: 258
Joined: Sat Aug 24, 2013 6:04 pm
Contact:

Re: Execution Speed. If vs =

Post by Wormbo »

You guys are over-complicating things.
How often, on average, will this code be executed per tick? If the answer is "less than about a dozen times", the correct way to implement it is "use whichever is easier to read", i.e. usually the simpler piece of code. Optimization simply isn't worth it.

If, for some reason, this piece of code must be executed a few hundred times per tick, the answer really depends on the more-probable game state. Can the additional code (variable access, object context, member access, constant, reference comparison, conditional jump) be executed in a time that brings the average execution time of the entire thing below that of the simpler version. (Assignment usually is a bit more expensive in UnrealScript than comparison, but not by as much as needed to make a significant difference.) My immediate reaction would be no, because it's too complex for that. Ultimately you will have to profile it to be sure.
Also, there's a difference between observed None and actual None. Destroyed actors remain referenced everywhere until the end-of-tick actor cleanup happens. Up until that point, most of UnrealScript will correctly see it as None, but some parts of the engine may not. So, if you really want it None, set it None regardless whether it already is.
MrLoathsome
Inhuman
Posts: 958
Joined: Wed Mar 31, 2010 9:02 pm
Personal rank: I am quite rank.
Location: MrLoathsome fell out of the world!

Re: Execution Speed. If vs =

Post by MrLoathsome »

I knew all the "cool" kids would like this question. :mrgreen:

Great answers.

Since this happens only once per tick, and I do really want it to be None, I will just stick with my initial simple line.

Code: Select all

		if (!bUseInv) ThePlayer.SelectedItem = None;
Thanks to all.
blarg
Post Reply