Jump to content
Leopard20

Code Optimization: Does setting variables to "nil" after usage help performance?

Recommended Posts

Hello everyone.

Currently I'm working on a mission which uses lots of "setVariables" for AI, and if a unit dies, it is deleted and a new unit is spawned instead (I have to use setVariable because it's hard to track all these variables using an array or something). That makes me wonder if these variables are now deleted or not. Basically a single unit could spawn a dozen times, and there could be as many as 50+ AI at any time in the game, which means lots of variables are constantly created, and thus slowing down the mission and consuming unnecessary RAM. If that's the case and the variables keep piling up, does setting them to nil (_unit setVariable ["SomeVar", nil]) help circumvent the issue?

P.S: The variables are relatively large in size, and most of them are arrays.

  • Like 1

Share this post


Link to post
Share on other sites
21 minutes ago, Leopard20 said:

Hello everyone.

Currently I'm working on a mission which uses lots of "setVariables" for AI, and if a unit dies, it is deleted and a new unit is spawned instead (I have to use setVariable because it's hard to track all these variables using an array or something). That makes me wonder if these variables are now deleted or not. Basically a single unit could spawn a dozen times, and there could be as many as 50+ AI at any time in the game, which means lots of variables are constantly created, and thus slowing down the mission and consuming unnecessary RAM. If that's the case and the variables keep piling up, does setting them to nil (_unit setVariable ["SomeVar", nil]) help circumvent the issue?

P.S: The variables are relatively large in size, and most of them are arrays.

 

When an object gets deleted, so should its namespace as far as I know.

setVariable even on thousands of objects within one frame shouldn't cause any issues, unless you broadcast them all.

 

Unless you run into performance issues and can pinpoint it to setVariable, I wouldn't worry too much about it.

 

Not really sure what you mean with having to use setVariable instead of an array.

 

Cheers

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
12 minutes ago, Grumpy Old Man said:

Not really sure what you mean with having to use setVariable instead of an array.

For example, I have a loop that runs on each frame to add "fake" animations to AI. The animation has several parameters, for instance positions to move through and the basic animation to play.

I could either define something like this (using setVar):
 

someArray pushback _unit;
{
 _animVar = _x getVariable ["MyAnims", [[],[],[]]];

} forEach someArray;

Or:

someArray pushback [_unit, [[],[],[]]];
{
	_x params ["_unit", "_animVar"];

} forEach someArray;

 

Now for the first case, If I wanted to change the animation, all I have to do is change the unit variable, but for the second case, I have to find the unit in the array and change it's animation using "set" which imparts some performance cost!

Share this post


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

Now for the first case, If I wanted to change the animation, all I have to do is change the unit variable, but for the second case, I have to find the unit in the array and change it's animation using "set" which imparts some performance cost!

You'll gain more performance by deleting a single AI from the mission.

 

Cheers

  • Like 1

Share this post


Link to post
Share on other sites
20 hours ago, Leopard20 said:

That makes me wonder if these variables are now deleted or not.

As soon as the body is deleted, they will be "deleted" yes. Atleast if we don't go into technical terms now.

 

20 hours ago, Leopard20 said:

and thus slowing down the mission and consuming unnecessary RAM

Consuming RAM yes, slowing down no, extra variables don't make stuff run slower.

 

20 hours ago, Leopard20 said:

If that's the case and the variables keep piling up, does setting them to nil (_unit setVariable ["SomeVar", nil]) help circumvent the issue?

Setting a variable to nil will waste more performance than just letting the variable lie around.

 

19 hours ago, Leopard20 said:

I have to find the unit in the array and change it's animation using "set" which imparts some performance cost!

"set" is essentially free. the find part is expensive.

 

Memory usage wise the array method is slightly better (about 50 bytes per AI unit difference). Performance wise the setVariable one is better because it's a hashtable lookup instead of a linear search.

  • Like 2

Share this post


Link to post
Share on other sites
2 hours ago, Dedmen said:

As soon as the body is deleted, they will be "deleted" yes. Atleast if we don't go into technical terms now.

 

Consuming RAM yes, slowing down no, extra variables don't make stuff run slower.

 

Setting a variable to nil will waste more performance than just letting the variable lie around.

 

"set" is essentially free. the find part is expensive.

 

Memory usage wise the array method is slightly better (about 50 bytes per AI unit difference). Performance wise the setVariable one is better because it's a hashtable lookup instead of a linear search.

Thanks for your reply. 

 

I was a bit concerned since I noticed my RAM gets filled up rather quickly when I play my mission (it still does fill up quick with all the mods I have installed compared to vanilla, but I think it's gotten worse). But since it's a relatively large scale mission I guess it makes sense.

 

I guess I'll stick with the setVariable method since there are lots of scripts running and performance matters more than the amount of memory consumed.

Share this post


Link to post
Share on other sites
2 minutes ago, Leopard20 said:

I was a bit concerned since I noticed my RAM gets filled up rather quickly when I play my mission

That is probably https://feedback.bistudio.com/T135718

It will be fixed in the next Arma update. Probably caused by simply bad code in mods/mission.

If it's your script just search for calls to "compile" or "compileFinal" and see if you can't do tha stuff differently.

  • Like 1

Share this post


Link to post
Share on other sites
7 minutes ago, Dedmen said:

That is probably https://feedback.bistudio.com/T135718

It will be fixed in the next Arma update. Probably caused by simply bad code in mods/mission.

If it's your script just search for calls to "compile" or "compileFinal" and see if you can't do tha stuff differently.

Maybe. But I don't compile my functions manually. They're all added to cfgFunctions.

Share this post


Link to post
Share on other sites

@Dedmen

If you don't mind, I have another question, but this time about local variables.

 

Let's say I have a script that has a local variable "_var". Then I call a function within that script. To prevent conflicting variables, which one is better? (in terms of both performance and memory consumption)

a. Defining a new local variable in the new function, such as _var1.

b. Using "private _var = ..." in the function.

 

Share this post


Link to post
Share on other sites
19 minutes ago, Leopard20 said:

@Dedmen

If you don't mind, I have an other question, but this time about local variables.

 

Let's say I have a script that has a local variable "_var". Then I call a function within that script. To prevent conflicting variables, which one is better? (in terms of both performance and memory consumption)

a. Defining a new local variable in the new function, such as _var1.

b. Using "private _var = ..." in the function.

 

 

Uhhh.... You should always put private infront of variables, you never know if you're missing something, and you also can't know when someone else might call your function.

Second always choose the variable name that makes sense. So just moving to a different var name might not be that optimal.

memory consumption wise it's the same, if you choose a different variable like _var1 instead of _var then, the name is one byte longer, thus one byte more memory usage ^^

Using private _var is also good practice to see where a variable is defined the first time.

  • Like 2

Share this post


Link to post
Share on other sites

I would say it depends. What is the variable for? If you are passing it to the function then use params as they also privates variables.

  • Like 1

Share this post


Link to post
Share on other sites
17 minutes ago, HazJ said:

I would say it depends. What is the variable for? If you are passing it to the function then use params as they also privates variables.

Good point. No, I meant an ordinary variable I intend to do some operations on.

 

Wait, that reminds me of yet another question! (sorry guys!)

 

If I wanted to perform an operation and get a variable out of it, is it advisable to define a new variable for every step?

For example:

Is this better:

_arr = [1, 2, 3]; //let's assume it has 100 elements!

_arr = _arr select {_x > 1};

_arr = _arr apply {_x+5};

than this:

_arr = ([1, 2, 3] select {_x > 1}) apply {_x + 5};

?

 

Another question. In the first snippet, if I WERE to define new variable on each step and the old variable is not needed anymore (e.g I won't be needing [1,2,3] later), should I keep replacing _var or define new variables such as _var1, etc.?

Share this post


Link to post
Share on other sites
12 minutes ago, Leopard20 said:

Is this better:

It's negligible. You can easily test that in debug console by just running a performance analysis thingy.
 

12 minutes ago, Leopard20 said:

should I keep replacing _var or define new variables such as _var1, etc.?

Replacing is better as you save the memory space for a new variable, which is about variable name length+20 bytes

IMO not really worth it.

Something to think about though is this:

{
    private _var = _x*2;
    ...
} forEach hugeArrayOfNumbers

vs

private _var = 1;
{
    _var = _x*2;
    ...
} forEach hugeArrayOfNumbers

 

In the first case you create a new variable each time, and delete it each time, but the lookup to find the variable is faster because it's so close in scope.
Second case the variable is further away in scope so lookup takes longer (we are talking nanoseconds here) but you don't constantly create/delete variables.

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
27 minutes ago, Leopard20 said:

Good point. No, I meant an ordinary variable I intend to do some operations on.

 

Wait, that reminds me of yet another question! (sorry guys!)

 

If I wanted to perform an operation and get a variable out of it, is it advisable to define a new variable for every step?

For example:

Is this better:


_arr = [1, 2, 3]; //let's assume it has 100 elements!

_arr = _arr select {_x > 1};

_arr = _arr apply {_x+5};

than this:


_arr = ([1, 2, 3] select {_x > 1}) apply {_x + 5};

?

 

Another question. In the first snippet, if I WERE to define new variable on each step and the old variable is not needed anymore (e.g I won't be needing [1,2,3] later), should I keep replacing _var or define new variables such as _var1, etc.?

I am on phone so can't help much but you can use params here too. Something like:

_arr = [10, ["Something", 100, TRUE], "LALALA"];

_var = _arr params ["_level", "_nestedArr", "_message"];

This saves you keep using select over and over. It is cleaner as you can use whatever _varName you want. Etc.

  • Like 2

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

×