Bump here with something which you might want to see...
Buggie is right somehow... but optimizing the code might deliver different results...
If you guys could not manage XC_Engine, it's not my loss, it's yours. XC_Engine has a clocking system where you can check the performance for executions. It was fascinating to see how people were following the SLOWEST solution and claiming that code was "changed for speed".
Let me see a foreach AllActors C++ native iterator compared to a linked list in UScript using 3 methods: "for" cycle, "While" and "do-until" like here:
Code: Select all
class Paths_Reporter expands Mutator;
function Mutate(string MutateString, PlayerPawn Sender)
{
local navigationpoint n;
local float Time[2];
local int np;
if ( MutateString ~= "nodes" )
{
class'XC_CoreStatics'.static.Clock(Time);
foreach AllActors ( class 'NavigationPoint', n )
np++;
log("Foreach Interator counted "$np$" nodes in"@class'XC_CoreStatics'.static.UnClock(Time)@"seconds.");
np = 0;
class'XC_CoreStatics'.static.Clock(Time);
for ( n = Level.NavigationPointlist; n != None; n = n.nextNavigationPoint )
np++;
log("For Cycle counted "$np$" nodes in"@class'XC_CoreStatics'.static.UnClock(Time)@"seconds.");
np = 0;
class'XC_CoreStatics'.static.Clock(Time);
n = Level.NavigationPointlist;
while (n != None)
{
np++;
n = n.nextNavigationPoint;
}
log("WHILE Linked list counted "$np$" nodes in"@class'XC_CoreStatics'.static.UnClock(Time)@"seconds.");
np = 0;
class'XC_CoreStatics'.static.Clock(Time);
n = Level.NavigationPointlist;
do
{
np++;
n = n.nextNavigationPoint;
}
until ( n == None );
log("DO-UNTIL Linked list counted "$np$" nodes in"@class'XC_CoreStatics'.static.UnClock(Time)@"seconds.");
np = 0;
}
if ( NextMutator != None )
NextMutator.Mutate(MutateString, Sender);
}
And bellow I'm going to show results for 180 Navigation Nodes, 562 Navigation Nodes and 751 Navigation Nodes - comparing some UT 440 with UT 469d...
PerfCounter wrote:
Performance Clocking Tests
UT 440
ScriptLog: Foreach Interator counted 180 nodes in 0.000015 seconds.
ScriptLog: For Cycle counted 180 nodes in 0.000026 seconds.
ScriptLog: WHILE Linked list counted 180 nodes in 0.000012 seconds.
ScriptLog: DO-UNTIL Linked list counted 180 nodes in 0.000011 seconds.
ScriptLog: Foreach Interator counted 562 nodes in 0.000027 seconds.
ScriptLog: For Cycle counted 562 nodes in 0.000084 seconds.
ScriptLog: WHILE Linked list counted 562 nodes in 0.000042 seconds.
ScriptLog: DO-UNTIL Linked list counted 562 nodes in 0.000038 seconds.
ScriptLog: Foreach Interator counted 751 nodes in 0.000025 seconds.
ScriptLog: For Cycle counted 751 nodes in 0.000100 seconds.
ScriptLog: WHILE Linked list counted 751 nodes in 0.000044 seconds.
ScriptLog: DO-UNTIL Linked list counted 751 nodes in 0.000040 seconds.
UT 469d
ScriptLog: Foreach Interator counted 180 nodes in 0.000016 seconds.
ScriptLog: For Cycle counted 180 nodes in 0.000027 seconds.
ScriptLog: WHILE Linked list counted 180 nodes in 0.000014 seconds.
ScriptLog: DO-UNTIL Linked list counted 180 nodes in 0.000014 seconds.
ScriptLog: Foreach Interator counted 562 nodes in 0.000028 seconds.
ScriptLog: For Cycle counted 562 nodes in 0.000080 seconds.
ScriptLog: WHILE Linked list counted 562 nodes in 0.000036 seconds.
ScriptLog: DO-UNTIL Linked list counted 562 nodes in 0.000035 seconds.
ScriptLog: Foreach Interator counted 751 nodes in 0.000028 seconds.
ScriptLog: For Cycle counted 751 nodes in 0.000103 seconds.
ScriptLog: WHILE Linked list counted 751 nodes in 0.000049 seconds.
ScriptLog: DO-UNTIL Linked list counted 751 nodes in 0.000046 seconds.
In ONLY ONE case UT 469d delivered a faster result using linked list. Mutator is using the same compilation, nothing was changed during testing stage.
Go figure out amazing codes like:
Code: Select all
for (P = Level.PawnList; P != None; P = P.nextpawn)
and
Code: Select all
for (N = Level.NavigationPointlist; N != None; N = N.nextNavigationPoint)
happily embedded in BotPack and some MonsterHunt variants as being used "for speed". These "FOR" cycles are just a mystical performance improvement - it's exactly the opposite direction - the slowest execution time compared even to other UScript solutions. The most entertaining part, compiler has nothing to do with these "coding" habits. Look well at 751 case: "do-until" vs "for" cycle it's 2 times different and UT widely uses "Level.PawnList" in "FOR" cycles for all sort of actions + Level.NavigationPointlist, yes, it's "BotPack.u".
Perhaps you understand that rewriting main functions are helping you more than using stock functions and calls to such a super-class.
Switching gear:
Someone pointed me that using more codes in "CheckReplacement" will result in a loss of performance. I'll bet on 10$ that codes can be different written and then... execution will be faster than in stock codes using the same "Compiler" which is restrictive to variables changed X times in C++ but UScript should not touch that "treasure" calling them "CONSTANTS" - it's a dumb rule for the sake of having rules and pain.