Jump to content
Sign in to follow this  
barbolani

Performance: count or scripted array check?

Recommended Posts

Hi!

 

As far as I know, if I have to iterate through a whole array to match a condition, count is the solution. Example {isPlayer _x} count playableUnits;

 

But, what if it's ok if just only one of the array elements match the condition?, I could use count: {isPlayer _x} count playableUnits > 0;

 

Or make a script like this:

_isThereOnePlayer =
{
_result = false;
{
if (isPlayer _x) exitWith {_result = true}
} forEach playableUnits;
_result
};

if ([] call _isThereOnePlayer) then {hint "There is one player!!"}

I suppose it depends on the array size, no real difference on iterating 5 elements than iterating through 1.

 

And also it is a matter of "luck": I may find the last element in the array matching the condition.

 

And also, count is an engine command and this function is a crap made by an Arma hobbyst.

 

But maybe I will have from you experts some "magic number", in the terms of: "If your array size has 500 elements, then use the scripted method, if less, use count"

 

Does it exist?

 

Thanks in advance!

Share this post


Link to post
Share on other sites

Did you try using the in game performance test?

Should have read the post. Sorry.

Using the in game performance tests the function was much faster.

This is because the count command will run through the entire array, while the function will exit as soon as it has found a player.

My test were with 101 units placed down.

You may want to instead try something like count (allPlayers - allDeadMen) > 0.

Share this post


Link to post
Share on other sites

What method of performance testing are you using?

 

Also please count you may have been lucky, this means player == playableUnits select 0, so the function exits very soon. Knowing the index on which the function has exit could be a good practice in a deep test.

Share this post


Link to post
Share on other sites

How about:

_result = ({if (isplayer _x) exitWith {1}} count playableUnits) >0;

Might be faster.

I tested with:

testarray = [16000,16000,0] nearObjects 1000;
testarray set [count testarray /2,player];

On Altis this created a 1100 item array with the player in the middle/or not.

  • Like 1

Share this post


Link to post
Share on other sites

How about:

_result = ({if (isplayer _x) exitWith {1}} count playableUnits) >0;

 

I've never knew you could use that formula in the count command!!!

Share this post


Link to post
Share on other sites

Took a shot at this.

All vanilla A3 with all current DLC, no mods running, tested on empty Altis.

_centerpos = getarray (configfile >> "CfgWorlds" >> worldName >> "centerPosition");
_size = getnumber (configfile >> "CfgWorlds" >> worldName >> "mapSize");
allBuildings = nearestObjects [_centerpos, ["Building"], (_size * 10)];

Using this on Altis returns an array of 21277 buildings.

 

 

 

Hiding the needle:

(allbuildings call BIS_fnc_selectRandom) setvariable ["test",true];

As expected, exitWith count is fastest:

{if (_x getvariable ["test",false]) exitWith {true}} count allbuildings;

39.0384 ms, fastest.

{if (_x getvariable ["test",false]) exitWith {true}} foreach allbuildings;

42.6661 ms, 9.29% slower than fastest.

{_x getvariable ["test",false]} count allbuildings;

44.9132 ms, 15% slower than fastest.

 

 

After resizing the array to 300 elements:

{if (_x getvariable ["test",false]) exitWith {true}} count allbuildings;

0.329702 ms, fastest.

{if (_x getvariable ["test",false]) exitWith {true}} foreach allbuildings;

0.367061 ms, 11.3% slower than fastest.

{_x getvariable ["test",false]} count allbuildings;

0.515733 ms, 56.2% slower than fastest.

 

Don't think there's anything faster than exitWith count, as long as you only need to find one needle.

Maybe KK and Larrow got a hint on this one.

 

Anyway, I guess I'll have to revisit some scripts of mine...

 

Cheers

Share this post


Link to post
Share on other sites

 

Anyway, I guess I'll have to revisit some scripts of mine...

 

 

While reading your post I was thinking the same :) Got a lot of work!!!

 

EDIT:

 

And why count is fastest than forEach?

Share this post


Link to post
Share on other sites

Looking at the wiki I can only guess, forEach is using _forEachIndex and can return anything,

count basically only evaluates a boolean check while returning numbers (unless you're using exitWith within the count loop).

 

That might explain the performance difference as far as I can think. (unless someone else can explain it, heh)

 

Cheers

Share this post


Link to post
Share on other sites

I also believe it's the _forEachIndex since both count and forEach do pretty much the same, only that count expects nil or a boolean as return value (and is still faster) while forEach doesn't care.

 

But if you don't like long inline efficient checks, use a constant (#define) like this:

#define IN_ARRAY(ELEMENT,ARRAY)    (1 isEqualTo {if(ELEMENT isEqualTo _x)exitWith{1}}count ARRAY)

if (IN_ARRAY(123,[551,21,123,13435,121,6,13])) then {
    ...
};

Share this post


Link to post
Share on other sites
Guest

Why dont you use allPlayers as Lala said.

You will get extra performance.

Or I did not understood what you are trying to do but wathever.

Share this post


Link to post
Share on other sites

No, you didn't :) The idea is to know the fastest way to know if there is a single true return among elements of any kind of array.

 

In my case it's important for the spawn system of Antistasi, as a zone is spawned with the presence of a single unit on certain distance, from that I don't want to iterate through the rest of the units array, as 1 is ok for me to spawn the zone.

 

You will see on the next update ;)

Share this post


Link to post
Share on other sites
Guest

Yep.

I understand then that the solution provided before is way more efficient. I discovered that kind of syntax a few weeks ago and i did not know that was even possible.

I'm still waiting for you to launch the rewrite of the mission as I got tired of working on something I dont know ^^. Forgive me. ^^.

Dont forget that I can help you with the github setup and other things.

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
Sign in to follow this  

×