zorrobyte 30 Posted December 5, 2014 Hello! I'm investigating CPS drop in my addon ZBE_Caching and require assistance in optimizing a condition. The code is: !({_x distance player < 1000} count (switchableUnits + playableUnits) isEqualTo 0) ["!({_x distance player < 1000} count (switchableUnits + playableUnits) isEqualTo 0);"] call BIS_fnc_codePerformance; 0.0121948ms 1 player 5 playableUnits This is important as when running on 144 groups: 1.7712144ms : 144 groups 1 player 5 playableunits - this is where CPS begins to drop assuming 60FPS as I have a sleep of 1 second between checks. Share this post Link to post Share on other sites
Defunkt 431 Posted December 5, 2014 I don't actually understand the syntax you're using there but I'll assume it's legal in whatever context you're using it. What I would say is you probably want to avoid concatenating the switchableUnits and playableUnits arrays just to count them, better to count them separately and add the results. Though I wouldn't have thought 1.7ms was an issue, did you mean 1.7s? Share this post Link to post Share on other sites
jshock 513 Posted December 5, 2014 (edited) I'm a little lost on the wording, but from what I think I understand: a single group of 6 entities takes ~0.012ms, but doing 144 groups of 6 enitities each takes ~1.77ms, but there is a suspension of one second between evaluation? Edited December 5, 2014 by JShock Share this post Link to post Share on other sites
zorrobyte 30 Posted December 5, 2014 (edited) !({_x distance unit1 < 1000} count (switchableUnits + playableUnits) isEqualTo 0) is a condition in a FSM that runs on each group that is checked every second. This condition takes 0.0121948ms to process, with 144 groups (144 FSMs) the combined total to check this condition is 1.7712144 seconds. As 1.7 seconds is longer than 1 second, other scripts begin to lag (my logic may be flawed here). Simply put, I'm looking for any way to check if a player is near a unit in a faster way. What I would say is you probably want to avoid concatenating the switchableUnits and playableUnits arrays just to count them, better to count them separately and add the results. I'll start here, I can build the "playable" units array in my main SQF loop that runs every 15 seconds instead of the FSMs that run every second x 144 times. Edited December 5, 2014 by zorrobyte Share this post Link to post Share on other sites
.kju 3245 Posted December 5, 2014 take a step back and explain first what you want to achieve Share this post Link to post Share on other sites
Tajin 349 Posted December 5, 2014 When doing frequent distance checks against a fixed value, it's better to use distanceSqr. That way the game doesn't have to pull the square root of the value every time. https://community.bistudio.com/wiki/distanceSqr I guess this is as good as it gets: !( { if (_x distanceSqr player < 1000000) exitWith {true}; } count (switchableUnits + playableUnits) isEqualTo 0 ) Also, switchableUnits are only relevant when you want that mission to work in SP. Which is rather pointless for most MP missions. Share this post Link to post Share on other sites
Larrow 2823 Posted December 5, 2014 (edited) This condition takes 0.0121948ms to process, with 144 groups (144 FSMs) the combined total to check this condition is 1.7712144 seconds Your conversion is off there Zoro. Ignoring the sleep for a moment... 0.0121948ms * 144groups = 1.7560512ms or 0.001756seconds 60fps == 1 / 60 = so 1frame is 0.016seconds or 16ms 0.016 / 0.001756 = 9.11 So your FSM would actually runs 9 times a frame, well potentially speaking, ignoring your sleep, other code and any engine overhead. Simply put, I'm looking for any way to check if a player is near a unit in a faster way. Im with .kju here, take a step back and explain what your overall goal is and how your currently doing it. No need to paste loads of code, just give us pseudo code of how things operate. Edited December 5, 2014 by Larrow Share this post Link to post Share on other sites
zorrobyte 30 Posted December 5, 2014 (edited) When doing frequent distance checks against a fixed value, it's better to use distanceSqr. That way the game doesn't have to pull the square root of the value every time. Thank you! I'm adding and testing now! Your conversion is off there Zoro. Ignoring the sleep for a moment...0.0121948ms * 144groups = 1.7560512ms or 0.001756seconds 60fps == 1 / 60 = so 1frame is 0.016seconds or 16ms 0.016 / 0.001756 = 9.11 So your FSM would actually runs 9 times a frame, well potentially speaking, ignoring your sleep, other code and any engine overhead. Derp, I shouldn't stay up all night and code while sick. Thanks! ;2832903']take a step back and explain first what you want to achieve Hello kju! I'm trying to solve CPS drop (script lag) in my caching module GIT REPO I'm currently seeking to optimize for uncache/cache event if players are near (the isNull is for AI<->AI cache/uncache check): zbe_cacheEvent = { ({_x distance _leader < _distance} count zbe_players > 0) || !isNull (_leader findNearestEnemy _leader) }; The other conditions are in the functions sqf (some are scattered in the FSMs until I can migrate them): zbe_func The faster I can make my conditions' date=' the less load my caching module has on the VM. My overall goal is to make CooP playable again with decent performance as AI kill servers. ZBE_Cache is CC-BY-SA and is one of the few caching modules compatible with just about any addon/script as I enablesimulation and hideobject all but leader instead of create/deletevehicle. As a bonus, ZBE_Cache allows thousands of empty vehicles spawned on the map as without, FPS massively drops for clients. I'll accept and credit any help provided up to and including GIT access. ---------- Post added at 06:40 PM ---------- Previous post was at 06:34 PM ---------- Hell, just posting the SS of my FSM helped, I see a error for reSync leader as uncache is linked to it for condition check and that I can remove my grpNull check for cache&uncache state as allDead should remove null groups :eek: Edited December 5, 2014 by zorrobyte Share this post Link to post Share on other sites
Zriel 12 Posted December 5, 2014 "There is actually 2 SQF VM Instances with Arma. One is shared scheduled / non scheduled shared. The other is used for FSM code only." http://killzonekid.com/arma-scripting-tutorials-code-performance/#comment-1206525222 Share this post Link to post Share on other sites
.kju 3245 Posted December 5, 2014 I think you are still to narrow with the description of your "problem". So let me put you a specific question to start with - why do you need to check that every more than every second? The condition can and still should be optimized, yet its important to look at the areas that matter most first. Share this post Link to post Share on other sites
Zriel 12 Posted December 5, 2014 The condition is not checked more than every second. It is checked every 3 or so "time frames" of te Arma engine. But the condition is checked by every AI group. Thus the need and questions to optimize it as much as possible. As in his example, 144 AI mean 144 checks every 3 secs. Share this post Link to post Share on other sites
fn_Quiksilver 1636 Posted December 5, 2014 I think a question to ask is, how often is it NECESSARY for the server to perform these evaluations? Every frame? Every 3 frames (as now)? Every 60 frames? Every 1-2 seconds? Every 10 seconds? Seems like such a performance-costly schedule is the problem, and something that definitely isn't going to improve much by trying to optimize the evaluation in question. It's still being performed many hundreds of times each second. Share this post Link to post Share on other sites
Zriel 12 Posted December 7, 2014 Dunno if wrong, but sleep 3 is a wait of 3 secs, isn't it? Not 3 frames. Share this post Link to post Share on other sites
fn_Quiksilver 1636 Posted December 7, 2014 (edited) Dunno if wrong, but sleep 3 is a wait of 3 secs, isn't it? Not 3 frames. Sleep does not work in FSM, and he's got 144 parallel FSMs running, one for each group. Many many thousands of evaluations per second. Not just evaluations, but world evaluations (distance checks). Optimization? You know what they say about lipstick and pigs? :) Optimizing an evaluation that happens thousands of times a second by using naval gazing optimizations that are measured in 3-5 decimal places (ie faster commands, lazy evaluations, and other stuff that produces barely-measurable and virtually unnoticeable effects)... Or structural optimization to go from thousands of evaluations a second, down to just a handful a second? As it is, there is not enough information provided to approach structural optimization, so IMO we are back to looking at a pig and deciding what color lipstick looks best :) No offense to you OP, just speaking my mind, and one way or the other your problems will be solved and all will be well in the end. EDIT: To be constructive: Since that FSM isn't a perpetual loop and it looks like there is great similarity from one FSM to the next (of the 144), I am of the mind that the best optimization would be to get rid of all the loops in the FSM (simplify it so it doesn't hang anywhere waiting for something), and then build a scheduler SQF and then feed the groups into the FSM one at at time in a loop. So instead of 144 FSMs running in separate threads, only one runs at a time. That would make the code almost 144x more performance-efficient. Just a side note ... This is the exact issue why AI are such a performance drag in ArmA. Each AI group/unit runs its own behaviour FSM thread, measuring distance to cover, enemies, near objects, waypoint calcs, terrain, rocks, targets, shots fired near, etc etc etc ...So OP, don't feel bad. This is how BIS does it too :) EDIT 2: More constructive ... This represents a structural optimization rather than IMO petty evaluation optimizations ... // FSM scheduler // Rough template, use for ideas // :) private ["_grpIndex","_grp","_fsmHandle"]; //========================== CONFIGURE YOUR GROUPS HERE ai_cacheGroups = []; // your managed groups { if (_x getVariable "ai_caching_group") then { // dreadedentity will chime in about alternative syntax here, go with what he suggests 0 = ai_cacheGroups pushBack _x; // find groups with your variable attached to them, to register them for management }; } count allGroups; // Any more groups data required for the FSM? Define it here // Stuff here is not checked again so consider it constants unless you redefine them at some point //========================== LOOP ai_caching = TRUE; while {ai_caching} do { // Can re-define stuff here if necessary, for use by each group // access changing variables/information here, IE player count may change, weather, time, FPS, etc. { _grpIndex = ai_cacheGroups find _x; _grp = ai_cacheGroup select _grpIndex; _fsmHandle = format ["fsm_%1",_grpIndex]; _fsmHandle = [_grp, /* any more data or variables you want to send to the FSM? */] execFSM "fsm\ai_caching.fsm"; waitUntil {sleep 0.1; (completedFSM _fsmHandle)}; // Wait for one FSM to complete before running the next } count ai_cacheGroups; }; Edited December 7, 2014 by MDCCLXXVI Share this post Link to post Share on other sites
Zriel 12 Posted December 8, 2014 (edited) Sorry, my bad. posting comments on phone wiithout thinking. We are doing this for delay: (time - _t) > 3; So basically, checks if the time minus the checked time in a previous FSM state is greater in 3 secs, to continue. But, your idea could be valid too. will give a try in this week. Edited December 8, 2014 by Zriel Share this post Link to post Share on other sites
zorrobyte 30 Posted December 9, 2014 That is one hell of a way to do it! I'm also on phone now and cannot reply in length as I wish but will try it out! Sent from my iPhone using Tapatalk Share this post Link to post Share on other sites
.kju 3245 Posted December 9, 2014 Is this assumption correct that your addon/system should be very generic not just specific to your mission/game mode? If so, it needs to account for dynamically added and removed units, as well as groups. You probably do this already, but MDCCLXXVI concept did not - being just a concept no problem there. Next thing is if you only want to check distance to the leader of the group, or to each individual unit. Like the units can be very much apart while the distance check is done. Also the question is on the player group/target group side - just account for the leader or each unit. Next thing is how you want to restore the position of the units once you uncache them - with their original setup/layout/offset, or just some generic one. Also keep in mind again spread out groups. Also is the distance check for uncaching done just on the leaders position, or do you take also the offset into consideration for the hidden units - also same story as above for the target leader and its units. Instead of running a FSM per group, you probably should add them all to an array and have this one array do the checks. Aka not multiple concurrent loops/checks, but one central system. Now you can also play how often the whole set of groups should be checked and if and what delay you want to add between checking each group. Overall a cycle refersh rate of a second or even slower should be OK - you could also regulate the frequency per unit type and the usual or actual travel speed (infantry = slow, vehicles = medium, air units = fast), as well as the caching distance (for longer distances a slower frequency doesnt matter much, while for close distance you may get the units to dis-/appear within sight or combat distance. Share this post Link to post Share on other sites
.kju 3245 Posted December 10, 2014 One thing to check with your original condition is whether the count approach, or a standard loop combined with exitWith on first unit within distance is faster. Another approach could be nearestObject - however I am doubtful that its faster. Share this post Link to post Share on other sites