Jump to content
Moerderhoschi

Codeperformance Question, one Thread per Unit or one Thread for all Units

Recommended Posts

I need some infomation to optimize some of my scripts, have somebody experienced performance impacts with to many spawned threads?

 

I need to know if there is a huge performance difference between the following two ways to execute some code. (the code is not timecritical)

 

Thread per Unit for ~ 300 units -> 300 new threads

{  [] spawn {  while {alive _x} do { somecode... }  }  } forEach allUnits;

One thread for all Units ~ 300 units -> 1 thread

while {true} do {  {  if (alive _x) then { somecode... }  } forEach allUnits };

thank you

Share this post


Link to post
Share on other sites

One for all!  B)

 

Does it have to run every tick though? You might want to add a sleep for performance if possible.

 

Also, it always worth considering if there's an alternative method to achieve the same thing or if a compromise can be made that simplifies the system. What's it for? Might be able to offer some alternatives.

Share this post


Link to post
Share on other sites

@SilentSpike Thank you for your answer. There is no explicit code, this is more a theoretical question. Have you made any negativ experience with to many spawned threads?

Share this post


Link to post
Share on other sites

It's just good practice to avoid loops where possible (that doesn't mean loops are bad, sometimes they're necessary). I see a lot of people use them in cases where event handlers would be more suitable.

  • Like 1

Share this post


Link to post
Share on other sites

@SilentSpike Thank you for your answer. There is no explicit code, this is more a theoretical question. Have you made any negativ experience with to many spawned threads?

I made a simple looting system that works by spawning a new thread at each of a building's positions, you can see it here:

 

I did not experience any kind of script slow-down, but then again I was testing the script on an empty mission, the only thing running was that script.

 

When code runs in a scheduled environment, each command gets sent to a queue and run when it's their turn. However, imagine that you had a sink that drained water at the same rate it added water. This will work indefinitely without the water building up, but if you take a cup and start pouring more water in it, the amount of water in the sink will slowly increase until it eventually overflows. Now imagine that the sink is the queue, the drain is how fast commands can be read, and the water is commands stored in the queue. Every time you spawn a new thread, dump a cup of water in the sink. If you spawn a thread with a loop, you're pouring a cup that never runs out. The sink is pretty full and even when you stop adding water, it will take some time for the existing water to drain out completely. This is what's known as script lag, when scripts take a long time to run their commands because there are way too many threads.

  • Like 1

Share this post


Link to post
Share on other sites

In theory there should be no difference, if the queue is filled up by one big thread or many small threads. But this is the core of the question.

The only thing i can imagine that the thread per unit method has, is additional reserved system resource for every new thread which could be an impact at many many threads.

Like i wrote, the whole topic is a very theoretical question and i wanted to hear some opinions from other scripters.

Thank you for your feedback so far :)

Share this post


Link to post
Share on other sites

I did some testing on a similar case, for my civilian agent FSMs.

With roughly 350-500 agents active within the players view it was no noticeable difference between having one FSM for each agent and one FSM checking all agents.

The mission was pretty busy with 25vs25 blufor/opfor firefight happening in the view distance, choppers flying by, artillery barrages and JSRS DragonFyre loaded (if that's even an indicator for increased cpu usage, didn't notice any either).

It really seems to be a GPU related performance drop having this many agents on the screen (probably hitting the polygon limit or something? units are pretty detailed)

 

When doing calculations for 2500 agents (object hidden and outside player view) there doesn't seem to be any noticeable CPU stress due to the conditions that need being checked (distance checks using distancesqr and a squared control distance with performance sleeps between each check etc.).

 

Unless you're not doing weird lineIntersect checks between hundreds of units in the same frame you should be fine doing it whatever way you prefer.

 

Cheers

  • Like 2

Share this post


Link to post
Share on other sites

@grumpy old man great feedback, thank you.

Yesterday i spend some time to optimize code with nearestObjects command. I checked first the complete island(Chernarus) once with nearestObjects radius of 20.000 meter for some specific buildingtypes with:

{_x addeventhandler ["killed",{_bomb = "BO_GBU12_LGB" createVehicle getPos (_this select 0)}]} forEach (nearestObjects
[
	[0,0],
	["Land_fuel_tank_small","Land_A_FuelStation_Shed","Land_Fuel_tank_stairs","Land_Ind_TankSmall","Land_Ind_TankSmall2"],
	20000
]);
This caused a huge game freeze/lag when the mission started and the code executed the first time. A better way to achieve the same result without freeze/lags was to check more smaller areas with nearestObjects command and add the buildings one after one to the final array. Finally i optimized the code to:

//FUEL TANKS BIG EXPLOSION
_fuelTankTypes = ["Land_fuel_tank_small","Land_A_FuelStation_Shed","Land_Fuel_tank_stairs","Land_Ind_TankSmall","Land_Ind_TankSmall2"];
_fuelTanks = [];
// LOOPING WITH SLEEP TO AVOID GAMEFREEZES
for "_i" from 0 to 20 do
{
	for "_i2" from 0 to 20 do
	{
		_factor = 1000;
		_fuelTanksTmp = (nearestObjects [[_i*_factor,_i2*_factor],_fuelTankTypes,_factor]);
		{if (!(_x in _fuelTanks)) then {_fuelTanks = _fuelTanks + [_x]}} forEach _fuelTanksTmp;
		sleep 0.01;
	};
};
{_x addeventhandler ["killed",{_bomb = "BO_GBU12_LGB" createVehicle getPos (_this select 0)}]} forEach _fuelTanks;
With this method the freeze was gone.

regards

Moerderhoschi

Share this post


Link to post
Share on other sites

@grumpy old man great feedback, thank you.

Yesterday i spend some time to optimize code with nearestObjects command. I checked first the complete island(Chernarus) once with nearestObjects radius of 20.000 meter for some specific buildingtypes with:

{_x addeventhandler ["killed",{_bomb = "BO_GBU12_LGB" createVehicle getPos (_this select 0)}]} forEach (nearestObjects
[
	[0,0],
	["Land_fuel_tank_small","Land_A_FuelStation_Shed","Land_Fuel_tank_stairs","Land_Ind_TankSmall","Land_Ind_TankSmall2"],
	20000
]);
This caused a huge game freeze/lag when the mission started and the code executed the first time. A better way to achieve the same result without freeze/lags was to check more smaller areas with nearestObjects command and add the buildings one after one to the final array. Finally i optimized the code to:

//FUEL TANKS BIG EXPLOSION
_fuelTankTypes = ["Land_fuel_tank_small","Land_A_FuelStation_Shed","Land_Fuel_tank_stairs","Land_Ind_TankSmall","Land_Ind_TankSmall2"];
_fuelTanks = [];
// LOOPING WITH SLEEP TO AVOID GAMEFREEZES
for "_i" from 0 to 20 do
{
	for "_i2" from 0 to 20 do
	{
		_factor = 1000;
		_fuelTanksTmp = (nearestObjects [[_i*_factor,_i2*_factor],_fuelTankTypes,_factor]);
		{if (!(_x in _fuelTanks)) then {_fuelTanks = _fuelTanks + [_x]}} forEach _fuelTanksTmp;
		sleep 0.01;
	};
};
{_x addeventhandler ["killed",{_bomb = "BO_GBU12_LGB" createVehicle getPos (_this select 0)}]} forEach _fuelTanks;
With this method the freeze was gone.

regards

Moerderhoschi

 

 

Could you not grab all those objects in the editor and save to a script?

 

Then you won't have to call nearestObjects at all! :)

 

 

 

for instance, here is all the fuel pumps on Altis:

//copyToClipboard str (nearestObjects [[15000,15000,0], ['Land_fs_feed_F'],30000]);

[
4b593900# 523012: fs_feed_f.p3d,
4bfc8100# 543336: fs_feed_f.p3d,
4bfbf200# 543425: fs_feed_f.p3d,
4cc34100# 492207: fs_feed_f.p3d,
4c197900# 491185: fs_feed_f.p3d,
4b222b00# 900373: fs_feed_f.p3d,
4a628800# 925581: fs_feed_f.p3d,
4b923200# 677190: fs_feed_f.p3d,
4b923900# 677189: fs_feed_f.p3d,
4b922b00# 677191: fs_feed_f.p3d,
4ac1eb00# 695890: fs_feed_f.p3d,
4c165d00# 450988: fs_feed_f.p3d,
4ba24f00# 602379: fs_feed_f.p3d,
4ccf6b00# 1665887: fs_feed_f.p3d,
4ba24800# 602380: fs_feed_f.p3d,
4ba25600# 602378: fs_feed_f.p3d,
4ccf7200# 1665886: fs_feed_f.p3d,
4a69eb00# 1020600: fs_feed_f.p3d,
4a69f200# 1020599: fs_feed_f.p3d,
4af2ab00# 814400: fs_feed_f.p3d,
4c30eb00# 580681: fs_feed_f.p3d,
4bc52b00# 1102299: fs_feed_f.p3d,
49398f00# 1085047: fs_feed_f.p3d,
4ca4eb00# 1592073: fs_feed_f.p3d,
4944e400# 1092999: fs_feed_f.p3d,
4944c100# 1092998: fs_feed_f.p3d,
48ebb200# 417716: fs_feed_f.p3d,
4ba62b00# 1457924: fs_feed_f.p3d,
496f5d00# 1128300: fs_feed_f.p3d,
4964e400# 1115097: fs_feed_f.p3d,
4964dd00# 1115098: fs_feed_f.p3d,
4c9f7200# 1573045: fs_feed_f.p3d
]

Share this post


Link to post
Share on other sites

I am also thought about this method, but the problem i see is when a island gets an update, all objects get new ID's and a prepared list will be obsolete.

This problem confronted me in the alpha/beta version of A3 many times.

Share this post


Link to post
Share on other sites

@SilentSpike the idea to gather the objects before the mission starts is not bad, but when i do it this way i see one challenge.

 

I use my scripts also/especially in ArmA 2 where i often use objectCompositions. Some of them also have some buildings which needed to be gathered by the script.

 

Then i would have to create the objectCompositions also during preinit before the script runs. So i dont know how this will impact the loadprocess at missionstart in Multiplayer, especially for the connected clients because at this point there will be a large amount of information transfered over the network to the clients, all before the briefingscreen show up.

Share this post


Link to post
Share on other sites

Then i would have to create the objectCompositions also during preinit before the script runs. So i dont know how this will impact the loadprocess at missionstart in Multiplayer, especially for the connected clients because at this point there will be a large amount of information transfered over the network to the clients, all before the briefingscreen show up.

It'd likely be even smoother than doing it at time 0. A slightly longer loading screen is no problem at all. There will be information transferred either way :)

  • Like 1

Share this post


Link to post
Share on other sites

I am also thought about this method, but the problem i see is when a island gets an update, all objects get new ID's and a prepared list will be obsolete.

This problem confronted me in the alpha/beta version of A3 many times.

 

How often has Altis been updated in the past 2 years?

 

Can even put in a small double-check before applying code, to ensure the object is what you think it should be, and throw an error/log should it not be.

 

I disagree with the idea that doing hundreds of nearestObjects scans to find the same objects each time is a good idea, if it can be avoided.

Share this post


Link to post
Share on other sites

It'd likely be even smoother than doing it at time 0. A slightly longer loading screen is no problem at all. There will be information transferred either way :)

 

thats a good point

 

How often has Altis been updated in the past 2 years?

Can even put in a small double-check before applying code, to ensure the object is what you think it should be, and throw an error/log should it not be.

I disagree with the idea that doing hundreds of nearestObjects scans to find the same objects each time is a good idea, if it can be avoided.

 

Sure, Altis will probably not be updated anymore(or not that often), but with checking all objects at missionstart, i will be ever up to date with the objects, no matter which island. Don't misunderstand me, i'm totally agree with you that your solution is the one with the best performance.

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

×