Jump to content
Robustcolor

forEach, count or apply

Recommended Posts

Hi, What are your opinions about using these commands in contexts like the one further down here when it comes to efficiency.

 

I read apply is faster then forEach with approximately 1%.

count seems to be faster with only approximately 0.01.ms.

 

3 examples;

apply = Applies given code to each element of the array and returns resulting array.

forEach = Executes the given command(s) on every item of an array. The array indices are represented by _forEachIndex.

count = the number of elements in array.

 

https://community.bistudio.com/wiki/Code_Optimisation suggests this

forEach loops, depending on the situation, can be replaced by:

apply

count

findIf

select

(units _grp01) apply {
_x setSkill 1;
_x setSkill ["AimingAccuracy",0.01];
_x allowFleeing 0;
};
{
_x setSkill ["AimingAccuracy",0.1];
_x allowFleeing 0;
} forEach (units _grp01);
{
_x setSkill ["AimingAccuracy",0.1];
_x allowFleeing 0;
} count (units _grp01);

 

Share this post


Link to post
Share on other sites

Unless you're actually running into performance issues I wouldn't worry too much about it.

Just use the commands for their intended purpose, if you need an index to work with, use forEach, for array manipulation use apply, etc.

 

To put it into perspective, considering a frame runtime of 16.6667ms at 60Hz, if one command is 0.01ms faster than another, it's still only a difference of 0.059% of the frames runtime.

Would hurt as much as throwing away 60 cents if you got a grand in your wallet.

 

Cheers

  • Like 1

Share this post


Link to post
Share on other sites

So since we don't need an result or index in this context the count is enough right? I've seen many scripts using forEach when setting skills etc for groups/units but what's the point with that? Is it necessary?

{
_x setSkill ["AimingAccuracy",0.1];
_x allowFleeing 0;
} count (units _grp01);

 

But between apply and forEach what's the big difference between them since they do almost the same? I know apply is great when using select in something like this

_alivePlayersUID = allPlayers select {alive _x} apply {getPlayerUID _x};

_playerDistances = _listeners apply {[_x distanceSqr _markerpos,_x]};

 

And last, how about forEach? When is it necessary?

_livePlayers = [];
{if (alive _x) then {_livePlayers pushBackUnique _x}} forEach allPlayers;

_alivePlayersUID = [];
{ 
if (alive _x) then {_alivePlayersUID pushpack (getPlayerUID _x)} 
}foreach allPlayers;

same as

_alivePlayersUID = allPlayers select {alive _x} apply {getPlayerUID _x};

 

The only time i noticed you really need the forEach command was when using an eventHandler and you want to use it on each units in a group.

Share this post


Link to post
Share on other sites

count vs foreach matters if you have to do it every frame, if you do it once the difference is so minuscule you need a microscope

Share this post


Link to post
Share on other sites

If you want to test it by yourself, write your working little code in debug console and click on the speedometer (left to server exec button)

Share this post


Link to post
Share on other sites

count, forEach, apply, select all do different things and all serve a specific purpose. Use whatever you need for whatever you want to do.

8 hours ago, Robustcolor said:

I read apply is faster then forEach with approximately 1%.

doesn't sound logical, as apply has to create a new array to return.

Share this post


Link to post
Share on other sites

How about using select vs all the options above?

[_grp01] select {
_x allowFleeing 0;
};

 

Share this post


Link to post
Share on other sites

Really?

What does mean [_grp01] an array of a unique group??

But, let's say, you thought about:     units _grp01    instead...

 

Using select instead of forEach is weird. The code (after select) will apply but you don't gain anything,

same for using apply instead of forEach , here also.

 

{_x allowFleeing 0} count units _grp01 // best but works when the code doesn't return anything (or just a boolean). Will return a count (of units here).

 

{_x allowFleeing 0} forEach units _grp01  // fine, readable, "universal" (without risk of error like with count when code returns some kind of non-boolean value)

 

units _grp01 select {_x allowFleeing 0}  // works (the code applies) but you don't gain anything and you return an empty array. Select should be used as intended: a TRUE/FALSE filter returning a sub-array like in:   units _grp01 select {fleeing _x}   however it's not the aim here.

 

units _grp01 apply {_x allowFleeing 0} // works but the weirdest solution. You'll obtain a [<null>,<null>,...<null>] array as return. The code applies with no added value, and perhaps slower than forEach. Use apply for an array transformation, not for applying such code.

 

So, for the readability and the optimization of your code, you'd rather use forEach (or count which is faster if your code returns nothing like here).

 

  • Like 2

Share this post


Link to post
Share on other sites

Thank you for such a good explanation @pierremgi

Changing forEach to count in these.

{
_x allowFleeing 0;
_x EnableDynamicSimulation true;
_x setBehaviour "COMBAT";
_x setCombatMode "RED";
_x setSpeedMode "FULL";
_x setFormation "LINE";
} count [_grp01];

{
_x setSkill 1;
_x setSkill ["AimingAccuracy",0.01];
} count (units _grp01);

 

Share this post


Link to post
Share on other sites

Why not:

_grp01 allowFleeing 0;

_grp01 EnableDynamicSimulation true;

_grp01 setBehaviour "COMBAT";

_grp01 setCombatMode "RED";

_grp01 setSpeedMode "FULL";

_grp01 setFormation "LINE";

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×