| Home Page | Recent Changes

UnrealScript Optimization

This page is about optimization of UnrealScript code. The UnrealScript compiler doesn't do any optimization by itself. In fact, doing stupid things that have no effect in other languages will have effect in UnrealScript.

However, you shouldn't take most of the content on this page serious. Why not? Because other code in your functions is mostlikely much slower than the optimizations listed here. But it doesn't hurt to know about these optimizations.

This page also covers comparissions between various methods to do certain things that might not be an optimization at all.

Useless code

The compiler doesn't drop useless statements. These statements are still compiled in byte-code and executed. Thefore these useless statements can hurt performance.

The following examples are all bad:

00001  switch (i)
00002  {
00003    case 1:
00004      ...
00005      break;
00006    ...
00007    default:
00008      ...
00009      break;
00010  }

The break on line #9 is useless, at the last case the switch will always go back to the main code. Adding this break will insert a jump to the next instruction, therefor useless. It doesn't have a major impact.

while (...)
{
  ...
  continue;
}

This example isn't as terrible as the former. In this case the continue is in fact useless and doesn't have a performance side effect. It only wastes a tiny bit of diskspace.

Basic arithmetic

00001  i = i+1; // BAD
00002  i += 1;  // better
00003  i++;     // good
00004  ++i;     // best
00005  
00006  i / 2;   // BAD
00007  i >> 1;  // good

El Muerte: I have a bit of a doubt here. What would be faster i /= 2 or i = i >> 1?

Switch`: i/=2 is faster, i*=0.5 is fastest.

Boolean evaluations

UnrealScript uses the so called short bool evaluation, meaning it will escape the boolean evaluation as soon as possible.

if (A || B) { ... }

If A is true it won't evaluate B because it already has a valid reason to execute the body of the if statement. You can use this to your advantage to optimize your boolean evaluations.

With and the right hand side isn't evaluated when the left hand side is already false. With or the right hand side isn't evaluated when the left hand side is already true.

Not all boolean expressions are fast as the others. For example string comparison is slower than a simple integer comparison. Thefore you should first compare types line integers, booleans, object references, floats, enumerations and names (yes names are actually integers with a friendly name) before comparing more complex types like strings and classes.

And ofcourse you should optimize the boolean expressions in the first place:

 ((A && B) || (B && C)) →  (B && (A || C))
 (A && B || !A && C || B && C) → (A && B || !A && C)

Variable accessing

00001  t = class.default.vc; // 428ms
00002  t = class'Sandbox'.default.vc; // 415ms
00003  t = default.vc; // 385ms
00004  t = vc; // 380ms
00005  t = self.vc; // randomly 406ms - 424ms...

TODO make more meaning out of this. source.

Jimboh: hmm...how about local variables vs class/object variables?

Out parameters

Defining function arguments as out will simulate passing by reference. But be careful with this. It doesn't actually pass the arguments by reference. It will copy the results back when the function exists. Because of this arguments defined as out are about twice as slow as arguments not defined as out.

Only native functions can use the out flag for true pass-by-reference instead of pass-by-value, but script functions can not.

Discussion

El Muerte: well, it's a start. We might need to think about a notation scheme for optimizations or something. Other items that could be address are:

local int x;
x = Rand(MaxInt);
doX(x);
doY(y);
doZ(z);

vs

doX(Rand(MaxInt));
doY(Rand(MaxInt));
doZ(Rand(MaxInt));

So far not a lot has been written on this subject. But quite some of these optimization tricks have been explored. So I think it's a good thing to dedicate a page on this subject.

SuperApe: Looks great. Useful stuff. Some of this might've even been helpful to Epic in earlier versions of Unreal. ;)

El Muerte: earlier?

Jimboh: Mabye merge with Code Optimization?

Jimboh: Hmm...does the final modifier (by itself) improve the speed of calling a function like it does in Java?

El Muerte: hmm... missed that page. Yes, final produces a significant speed improvement. For the simple reason that it will cut the function lookup short.

The Unreal Engine Documentation Site

Wiki Community

Topic Categories

Recent Changes

Offline Wiki

Unreal Engine

Console Commands

Terminology

FAQs

Help Desk

Mapping Topics

Mapping Lessons

UnrealEd Interface

UnrealScript Topics

UnrealScript Lessons

Making Mods

Class Tree

Modeling Topics

Chongqing Page

Log In