Jump to content
igneous01

call too slow - way to inline code passed as parameter?

Recommended Posts

I have some functions that are used to generate / obtain a subset from a collection, with a predicate as an argument (a form of Inversion of Control), but the problem is that the call generates a lot of overhead.

fnc_generate = {
	params["_size", "_initV", "_pred"];
	private _array = [];
	private _it = _initV;
	for [{_i = 0}, {_i < _size}, {_i = _i + 1}] do
    {
        _array pushback (call _pred);                        
    };   
    _array;
};
fnc_subset = 
{
	params["_array", "_pred"];
	private _collection = [];
	{
		if (_x call _pred) then { _collection pushback _x; };
	} foreach _array;
	_collection;
};


I'm comparing doing the following:

// Manual way
BIGARRAY = [];
for [{_i=0}, {_i < 10000}, {_i = _i + 1}] do
{
      BIGARRAY pushback _i;
};
// 45 ms avg
                          
BIGARRAY = [];
BIGARRAY = [10000, 0, {_it = _it + 1; _it;}] call fnc_generate;
// 68 ms avg
                          
                          
// manual way
SUBSET = [];
{
	if (_x > 10) then { SUBSET pushback _x; };
} forEach BIGARRAY;

// 47 ms avg

SUBSET = [];
SUBSET = [BIGARRAY, {_this > 10;}] call fnc_subset;

// 69 ms avg

 

Adding call makes the code ~28% slower, and this starts to get noticeable if you are doing things like this often/with larger sets of data.

Is there a way to inline the predicate so that it just replaces (call _pred) with the predicate code the user passed in?

Macros have a way of doing this sort of replace, but the problem is you cant use preprocess commands on a function, only on a filepath.

Share this post


Link to post
Share on other sites

At least you can resize array after creation to avoid reallocations and remove excess _initV variable:

fnc_generate = {
	params["_size", "_it", "_pred"];
	private _array = [];
	_array resize _size;
	for [{_i = 0}, {_i < _size}, {_i = _i + 1}] do {
    		_array set [_i, call _pred]};   
    _array
};

Fixed set command, thanks killzone_kid

  • Like 1

Share this post


Link to post
Share on other sites

Your fnc_subset can be easily "inlined" with:

private _result = _array select {_x call _pred};

 

  • Like 2

Share this post


Link to post
Share on other sites
1 hour ago, serena said:

Your fnc_subset can be easily "inlined" with:


private _result = _array select {_x call _pred};

 

that's a new one, I'm glad they added in select with expression, means I don't need to create a subset function to do this. How fast is this method?

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

×