Jump to content
🛡️FORUMS ARE IN READ-ONLY MODE Read more... ×
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

×