Code Optimisation – Talk

From Bohemia Interactive Community
Jump to navigation Jump to search
m (Text replacement - "<code>" to "<code style="display: block">")
m (Text replacement - "Killzone Kid" to "Killzone_Kid")
 
Line 285: Line 285:
//0.0727051 ms</code>
//0.0727051 ms</code>


[[User:Killzone Kid|Killzone Kid]] ([[User talk:Killzone Kid|talk]]) 22:58, 5 July 2015 (CEST)
[[User:Killzone_Kid|Killzone_Kid]] ([[User talk:Killzone_Kid|talk]]) 22:58, 5 July 2015 (CEST)


== Historic keeping (might still be true for older games) ==
== Historic keeping (might still be true for older games) ==

Latest revision as of 13:48, 12 March 2024

This article is brilliant. Thank you --Doolittle 16:57, 28 April 2010 (CEST)

Agree. ;) Very good information about how to make things work better. --SNKMAN 22:51, 8 August 2010 (CEST)


I want to open a discussion, if the use of the Global Array System should be recommended here at all
or at least it needs the following points as comments to take into account when reading about it.

The system was originally developed to avoid the GV limit for savegames in OFP.
This is no longer a problem, so no longer an argument to use this design.

Here are a couple of points we gather that argue against the use of this design:

1. Memory use

  • We cannot really judge if it takes less memory, as we do not know the implementation.
  • A large array itself may even take more; especially if not all elements are set.
  • You can't undefine not used variables easily.

2. Performance

  • Multiple selects from a huge array is most likely slower than referencing global variables.
  • You always have to work with this monster of array.
  • And use "select" and "set" to modify it instead of simple variable assignment.

3. Code design

  • The array design is hard to read and to understand.
  • The lack of variable naming makes it even worse.

Anyone is welcome to comment this. Ty. --Kju 08:30, 9 August 2010 (CEST)


Well to me it's a pretty good way having all "Global Variables" of a specific feature stored in 1 array instead of creating 3 - 5 and more "Global Variables" for the most feature.
Of course it will need some practice for use and understand how it works.
Just thought i should share this with others so everybody knows a second way of how it can be made.
If you think it's not need then simply remove it from the page.
Not a big problem at all. ;) --SNKMAN 17:49, 9 August 2010 (CEST)
It is good to have it explained, I agree. What I argue is that this is not the right place.
The page says code optimization and to me the design is quite the contrary.
So I'd suggest to move it to a new page and reference it for example. --Kju 07:04, 10 August 2010 (CEST)
Okay so i will move this into my private wiki talk then. --SNKMAN 09:30, 10 August 2010 (CEST)
Your private talk is no good. It will not be visible enough that way and not found by others.
Create a new dedicated page for the system and move the relevant comments from this talk page to its talk page. --Kju 11:43, 10 August 2010 (CEST)

Anyway... I have a question about a point in this article: The "The 0.3ms delay" could anyone explain this a little bit more in detail please? I don't really get the point... When exactly is this 0.3ms delay needed? Only in scripts/functions which was executed after the mission was initialized and started? Many thanks and keep this page growing. :) --SNKMAN 17:49, 9 August 2010 (CEST)

Anything started with execvm/spawn will be under the engine's script scheduler's powers. If it thinks your script takes too long to execute, it will pause it (to let other scripts have some CPU time as well) for a unspecified time (that 3/0.3/0.03ms is probably a guess, as it most likely depends on the FPS the machine is running). Shuko 18:23, 9 August 2010 (CEST)
See New to Arma 2: The "3ms-break" --Kju 07:04, 10 August 2010 (CEST)
Many thank's guy's. --SNKMAN 09:30, 10 August 2010 (CEST)



Call without scheduling

How about to add following function?

// Execute code in one (game) tick 
// [code, arglist] call rls_func_callWithoutScheduling
modname_func_callWithoutScheduling = {
    private "_logic";
    _logic = "logic" createVehicleLocal [0,0];
    _logic setVariable ["/ModName/CallWithoutScheduling/Data", _this];
    _logic addEventHandler ["killed", {
        (_this select 0) call {
            _this getVariable "/ModName/CallWithoutScheduling/Data" call {
                (_this select 1) call (_this select 0);
            };
            deleteVehicle _this;
        };
    }];
    _logic setDamage 1;
};

denisko.redisko 22:49, 2 September 2010 (CEST)

Think about it again. The logic creation and setDamage part run in a scheduled environment and can be delayed.
You could also run the code in the function instead in the killed EH, wouldn't make a difference Xeno 09:16, 3 September 2010 (CEST)
Additionally have a look at; https://wave.google.com/wave/waveref/googlewave.com/w+_n2bnMknJ Nou's implementation works pretty well at least on clients/SP. Sickboy 15:22, 25 September 2010 (CEST)

Check this code:

0 spawn {
    call {
        sleep 1; // no error, becouse this code will execute with scheduling
        waitUntil { false }; // no error, becouse this code will execute with scheduling
    };
};
[{
    sleep 1; // error, this code must execute without scheduling (in one tick)
    waitUntil { false }; // error, this code must execute without scheduling (in one tick)
}, []] call rls_func_callWithoutScheduling

More examples:

// 0 execVM "script1.sqf"
call {
    disableSerialization;

    findDisplay 46 createDisplay "RscDisplayDiary";
    _listbox1 = findDisplay 129 displayCtrl 1001;
    _listbox2 = findDisplay 129 displayCtrl 1002;

    for "_i" from 0 to 10000 do {
        _index = _listbox1 lbAdd format ["item %1", _i];
    };
    // Second listbox will be drawn much later.
    for "_i" from 0 to 10000 do {
        _index = _listbox2 lbAdd format ["item %1", _i];
    };

    hint "OK";
};
// 0 execVM "script2.sqf"
[{
    disableSerialization;

    findDisplay 46 createDisplay "RscDisplayDiary";
    _listbox1 = findDisplay 129 displayCtrl 1001;
    _listbox2 = findDisplay 129 displayCtrl 1002;

    for "_i" from 0 to 10000 do {
        _index = _listbox1 lbAdd format ["item %1", _i];
    };
    // Is rendered instantly.
    for "_i" from 0 to 10000 do {
        _index = _listbox2 lbAdd format ["item %1", _i];
    };

    hint "OK";

}, []] call modname_func_callWithoutScheduling;

denisko.redisko 03:55, 25 September 2010 (CEST)


Wow, that's exactly what the doctor ordered! Applying this to trick to dumpConfig speeds things up big time. Thanks for sharing! :) Worldeater 06:42, 29 September 2010 (CEST)

Fast dump of the game config? Try it :) http://www.ofpec.com/forum/index.php?topic=35236.0 denisko.redisko 10:18, 3 October 2010 (CEST)

The problem still remains :) It depends on where you execute the code. If you start the dump from a normal script started with execVM or spawn then it will be massively delayed. Calling the dump from a trigger for example is fine (or from an EH or UI function or any other non scheduled environment). But as long as the function which starts the EH or UI function is also running in a scheduled environment it can be delayed too. Xeno 11:01, 3 October 2010 (CEST)

About it and talking. But suppose we need to execute code in a one tick in a scheduled environment, such as:

// we need use addAction, but showDialog.sqf must be runs in a non scheduled environment
_object addAction ["show dialog", "showDialog.sqf"]

Your solution? denisko.redisko 07:27, 4 October 2010 (CEST)

Measuring Velocity Scalar

Sure we can just use Pythagorean theorem to calculate the magnitude from a velocity vector, but a command native to the engine runs much faster (over 10x faster) than the math.

Works for 2D vectors as well.

NOTE: Distance command as it stands cannot be used for this method because of its specifics (see distance). A not yet implemented distanceASL command would be the correct choice. So until then moving this here.

switch is faster than call if exitwith with many conditions

Moved from main page:

Choose wisely between call { } and switch()
Test results with Arma 3 1.46 Debug console using for loop on a 32-size switch and a call 32-times if exitWith:

'''500 times:'''
switch: 11.2936ms
call: 13.3026ms

'''1 000 times:'''
switch: 22.5152ms
call: 26.579ms

'''5 000 times:'''
switch: 113.444ms |
call: 133.124ms

'''10 000 times:'''
switch: 245.41ms |
call: 265.499ms

'''50 000 times:'''
switch: 1172.12ms |
call: 1328.99ms

'''100 000 times:'''
switch: 2263ms |
call: 2634ms

'''500 000 times:'''
switch: 11275ms |
call: 13193ms 

'''1 000 000 times:'''
switch: 24867ms |
call: 26536ms

NOTE: The reason why switch is faster in this case: short conditions. the call version had more code to read.
But the idea still applies :)

Here are my results:

call { if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (false) exitWith {}; if (true) exitWith {}; }; //0.0583008 ms

switch (true) do { case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case false: {}; case true: {}; } //0.0727051 ms

Killzone_Kid (talk) 22:58, 5 July 2015 (CEST)

Historic keeping (might still be true for older games)

Position World is the fastest

getPosASL and visiblePositionASL are almost 2x faster than getPos, position and visiblePosition. Even

ASLtoATL getPosASL _obj;

is ~30% faster than

getPos _obj; Note that getPosATL and getPosASL are equally as fast in Arma 3 (tested in v1.22).

You can use this function where _this is the object you want to find the position of. FNC_GetPos = { private "_pos"; _pos = getPosASL _this; if !(surfaceIsWater _pos) then { _pos = ASLToATL _pos; }; _pos };

But new to Arma 3 command getPosWorld is the fastest of them all.