Moerderhoschi 106 Posted August 29, 2015 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
SilentSpike 84 Posted August 29, 2015 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
Moerderhoschi 106 Posted August 29, 2015 @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
SilentSpike 84 Posted August 29, 2015 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. 1 Share this post Link to post Share on other sites
dreadedentity 278 Posted August 29, 2015 @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. 1 Share this post Link to post Share on other sites
Moerderhoschi 106 Posted August 29, 2015 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
Grumpy Old Man 3540 Posted August 30, 2015 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 2 Share this post Link to post Share on other sites
Moerderhoschi 106 Posted August 31, 2015 @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
fn_Quiksilver 1633 Posted August 31, 2015 @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
Moerderhoschi 106 Posted August 31, 2015 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 84 Posted August 31, 2015 You could collect them all during preInit too :) Share this post Link to post Share on other sites
Moerderhoschi 106 Posted August 31, 2015 @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
SilentSpike 84 Posted August 31, 2015 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 :) 1 Share this post Link to post Share on other sites
fn_Quiksilver 1633 Posted August 31, 2015 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
Moerderhoschi 106 Posted August 31, 2015 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