Jump to content
Sign in to follow this  
KaRRiLLioN

Multiple instances of SQF's bad for server?

Recommended Posts

I had several missions, CTF's and C&H's that would experience strange crashes.  Well, not crashes exactly.  The server would still be running and each player could move around, but remote players and AI would appear frozen to each other.  In other words, as if the server had stopped sending updates to clients.

I observed that the dedicated server was eating up all CPU power when this happened.  Yet, it was still running.

I had most vehicles on the map respawning with my vrs.sqf script, each vcl running a separate instance of it.  It's virtually identical to my SQS version, except, of course, the syntax.  Both scripts are server-side only.  In each case, the number of instances was about 12 to 15.

I changed all instances to instead use the SQS version and voila, the games proceeded without the dedicated server freezing like that.

From this it appears that multiple instances of looping SQF files are bad for the server.  And I say server in this intance because the scripts were server-side.  I don't know what it might be like if there were some running client side.

I assume that since SQF takes priority over many things, the server is unable to devote enough processor time to other functions.  Then again, my code might be complete crap.  

Just in case that's so, here's the code.

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">

//BEGIN vrs.sqf

//By KaRRiLLioN

//IMPORTANT: ADD A GAMELOGIC NAMED Server

//to the mission to prevent multispawn

private ["_vcl","_respawndelay","_dir","_pos","_type","_run","_crewWait","_wait","_delay"];

if (!local Server) exitWith {};

_vcl = _this;

_respawndelay = 20;

_dir = Getdir _vcl;

_pos = Getpos _vcl;

_crewWait = 150;

_wait = 0;

_type = typeOf _vcl;

_run = TRUE;

sleep 1;

for [{}, {_run}, {_run}] do

{

   while {canMove _vcl && count crew _vcl < 1} do

   {

        _wait = Time + _crewWait;

        sleep 1;

   };

   while {Count crew _vcl > 0 && Alive _vcl} do

   {

        _wait = Time + _crewWait;

        sleep 1;

   };

   while {canMove _vcl && count Crew _vcl < 1 && Time < _wait} do

   {

        sleep 1;

   };

   _delay = Time + _respawnDelay;

   while {!canMove _vcl && count Crew _vcl < 1 && Time < _delay} do

   {

        sleep 1;

   };

   if (count Crew _vcl < 1) then

   {

        deleteVehicle _vcl;

        _vcl = _type createVehicle _pos;

        _vcl setdir _dir;

        sleep 1;

        _vcl setvelocity [0,0,0];

        _vcl setpos _pos;

        sleep 1;

        _vcl setvelocity [0,0,0];

   };

};

So, is my theory completely amiss?  Or might it hold water?

Share this post


Link to post
Share on other sites

I didn't test that, but are you sure that for allows sleeps? forEach doesn't, afair... huh.gif

Share this post


Link to post
Share on other sites
I haven't used the FOR loop yet but just looking at it in the wiki

I can't see how your loop ends.

That's done intentionally that way I think as while do exits after 9999 loops...

Share this post


Link to post
Share on other sites

Right, it's an infinite loop.  In this case I'm talking strictly about infinite looping SQF's not run-once.  So long as there's an exit from an SQF loop, I can't see that it would sieze all CPU power on the server for a noticeable length of time.

Oh, and this is exec'd using execVM.

Share this post


Link to post
Share on other sites
Right, it's an infinite loop. In this case I'm talking strictly about infinite looping SQF's not run-once. So long as there's an exit from an SQF loop, I can't see that it would sieze all CPU power on the server for a noticeable length of time.

Oh, and this is exec'd using execVM.

Still, are you sure that for (even if execVM'ed) really "uses" the sleeps? As said, I didn't test that. whistle.gif

Share this post


Link to post
Share on other sites

I tested and confirmed. The sleeps do work. I put in several sleeps of differing length with some debug text and the intervals worked as they should.

Since I know I have sleeps in every loop of at least 1 second, it concerns me if SQF's do eat up that much CPU.

Share this post


Link to post
Share on other sites
I tested and confirmed. The sleeps do work. I put in several sleeps of differing length with some debug text and the intervals worked as they should.

Since I know I have sleeps in every loop of at least 1 second, it concerns me if SQF's do eat up that much CPU.

Damn, then this has to be a bug... confused_o.gif

Share this post


Link to post
Share on other sites

Just a hunch, but it might be worth a try...

Put a sleep into the outermost loop, not just into the while constructs.

And I would also try to replace the whiles with waitUntil, as they seem to be a bit less CPU-intensive, and more suited for your sequential tests anyway.

Share this post


Link to post
Share on other sites

Maybe some of the commands used are causing issues? Did you try removing them step by step to see if it helps in anyway?

I'm running at least 50 times the same SQF script which checks the distance between 50 locations and a changing a mount of players and other units on the map.<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">

///////////////////////////////////////////////////////////

// ArmA - dacmon.sqf by Sickboy (sb_at_6thSense.eu)

//

///////////////////////////////////////////////////////////

   private["_run","_act","_sleep","_s","_grp","_bl","_side","_pos","_unit","_ac","_da","_ad","_di","_a1","_a2","_a3","_ho","_y","_z","_act2","_acc","_dac","_grpla","_us"];

   _us=_this select 0;

   _pos=_this select 1;

   _ac=_this select 2;

   _da=_this select 3;

   _ad=_this select 4;

   _side=_this select 5;

   _bl=_this select 6;

   _ho=_this select 7;

   _run=true;_act=false;_bl=true;_s=700;_s2=400;_act2=false;

   _di=_ad+600;

   _acc=_ac+500;

   _dac=_da+500;

   _z={{deletevehicle _x;} foreach (units _grp);sleep 1;_grpla=format["%1",_grp];while{((format["%1",_grp])!="<NULL-group>")}do{sleep 2;deletegroup _grp;};if(six_debug_miss&&six_isClient)then{player sideChat format["BUILDINGS: %1 was nullified",_grpla];};};

   switch _side do

   {

       case "EAST": {_unit=["SoldierEB","SoldierESniper"];_y={_grp=creategroup east;[_grp,_pos,_ad,22,_unit] call spawnbuild;};};

       case "WEST": {_unit=["SoldierWB","SoldierWSniper"];_y={_grp=creategroup west;[_grp,_pos,_ad,22,_unit] call spawnbuild;};};

       case "RESISTANCE": {_unit=["SoldierGB","SoldierGSniper"];_y={_grp=creategroup resistance;[_grp,_pos,_ad,22,_unit] call spawnbuild;};};

   };

   waitUntil{six_init};

   sleep (random 10);

   while{_run}do

   {

       while{_run}do

       {

           _sleep=10;

           if(_ho)then

           {

               _a3={((alive _x)&&((_x distance _pos)<_ad+_s2))} count DAC_Players;

               sleep 1;

               if(_a3>0)then

               {

                   if(!_act2)then

                   {

                       call _y;_act2=true;_s2=600;

                       if(_bl)then

                       {

                           if(!(_acc in DAC_Activate))then{DAC_Activate=DAC_Activate+[_acc];};

                           if(_dac in DAC_DeActivate)then{DAC_DeActivate=DAC_DeActivate-[_dac];};

                       };

                   };

               } else {

                   if(_act2)then

                   {

                       call _z;_act2=false;_s2=400;

                       if(_bl)then

                       {

                           if((_acc in DAC_Activate))then{DAC_Activate=DAC_Activate-[_acc];};

                           if(!(_dac in DAC_DeActivate))then{DAC_DeActivate=DAC_DeActivate+[_dac];};

                       };

                   };

               };

               sleep 2;

           };

           _a1={((alive _x)&&((_x distance _pos)<(_ad+_s)))} count call compile _us;

           sleep 1;

           _a2={((alive _x)&&((_x distance _pos)<(_di+_s)))} count DAC_Players;

           sleep 1;

           if((_a1+_a2)>0)then

           {

               if(!_act)then

               {

                   _act=true;_s=950;_sleep=30;

                   if(!(_ac in DAC_Activate))then{DAC_Activate=DAC_Activate+[_ac];};

                   if(_da in DAC_DeActivate)then{DAC_DeActivate=DAC_DeActivate-[_da];};

               };

           } else {

               if(_act)then

               {

                   _act=false;_s=700;_sleep=30;

                   if(_ac in DAC_Activate)then{DAC_Activate=DAC_Activate-[_ac];};

                   if(!(_da in DAC_DeActivate))then{DAC_DeActivate=DAC_DeActivate+[_da];};

               };

           };

           sleep _sleep;

       };

       sleep 0.001;

   };

aswell as many others without any hassle... smile_o.gif

Share this post


Link to post
Share on other sites
Hehe...

Sickboy has too much time wink_o.gif

Or just deeply in love with ArmA (&Scripting) biggrin_o.gif

Share this post


Link to post
Share on other sites

so is SQF or SQS better?

i have only used SQS till now, cause i got it from OFP.

Share this post


Link to post
Share on other sites

Me too... but currently not time for SQF.

I´ll do it in future. Now I´m too busy.  crazy_o.gif

SQF ist the future! It works more better than SQS and you´ll have more abilities.

Sickboy... that´s your part wink_o.gif

Share this post


Link to post
Share on other sites
so is SQF or SQS better?

i have only used SQS till now, cause i got it from OFP.

If you ask me .. it is simply better. But how much, aswell as performance wise, is just depending on what you do with it...

My reasons for SQF:

[*] Precompile at start, then spawn the script instance from memory every time you need it, while SQS get read everytime from your harddrive, even during scriptrun (you can even change scripts while running)! Loading from memory is ALWAYS better IMHO... But it will loan especially when you have many and/or many of the same scripts running/unloaded/loaded etc.

[*] More proper and better overviewable code, you dont have to write all in 1 row like in SQS, but you can use multiple rows for a good logical programming way.

[*] In my eyes a better scripting language logic... the sqs with goto's etc was maybe easy, but too much .bat/basic-ish smile_o.gif I simply prefer the use of waituntil, while, for, switch/case etc... Besides, try to debug an sqs with 10 #points and 30 goto's :P

But I think we already have a topic for this smile_o.gif

Quote[/b] ]Me too... but currently not time for SQF.

I´ll do it in future. Now I´m too busy.  crazy_o.gif

SQF ist the future! It works more better than SQS and you´ll have more abilities.

Sickboy... that´s your part wink_o.gif

Hehe, yeah I was a bit dissapointed to find your Artillery examples in SQS format... Was in need of a fast source for Artillery but im not infecting my Scripting Framework with SQS :P

I'm building a shared development area with a few ppl, if anyone is interested... take a look: http://trac.6thsense.eu:800/arma/trac

Under Construction... There is a shared source which is linked with subversion for version control (but only accessible for the devs), history/log overview and diff-creations between different versions for extra overview and insights in code changes smile_o.gif Aswell as bugtracking system... I'm trying to get as much ppl in there as possible... The level of working together is decided by the devs themselves, if they work on their own projects, then they still have access to a good information base and code source smile_o.gif

Share this post


Link to post
Share on other sites

My tests show that counting crew in a dead vehicle cause's a crash

can someone with more scripting knowhow test this

edit: tested not the problem....might be the while loop logic

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">//BEGIN vrs.sqf

//By KaRRiLLioN

//IMPORTANT: ADD A GAMELOGIC NAMED Server

//to the mission to prevent multispawn

private ["_vcl","_respawndelay","_dir","_pos","_type","_run","_crewWait","_wait","_delay"];

if (!local Server) exitWith {};

_vcl = _this;

_respawndelay = 20;

_dir = Getdir _vcl;

_pos = Getpos _vcl;

_crewWait = 150;

_wait = 0;

_type = typeOf _vcl;

_run = TRUE;

sleep 1;

for [{}, {_run}, {_run}] do

{

while {canMove _vcl && count crew _vcl < 1} do

{

_wait = Time + _crewWait;

sleep 1;

};

while {Count crew _vcl > 0 && Alive _vcl} do

{

_wait = Time + _crewWait;

sleep 1;

};

while {canMove _vcl && time < _wait} do

{

sleep 1;

};

if (!Alive _vcl) then

{

deleteVehicle _vcl;

_vcl = _type createVehicle _pos;

_vcl setdir _dir;

sleep 1;

_vcl setvelocity [0,0,0];

_vcl setpos _pos;

sleep 1;

_vcl setvelocity [0,0,0];

};

};

this seems to work but I've had to many computer resets to test anymore and I'm not sure if the logic suits your purpose. banghead.gif

Share this post


Link to post
Share on other sites

@Sickboy

Quote[/b] ]Hehe, yeah I was a bit dissapointed to find your Artillery examples in SQS format... Was in need of a fast source for Artillery but im not infecting my Scripting Framework with SQS :P

It´s not a problem... because there were some peoples who wanted a solution for this topic and I realized it with a script.

The main thing is, that it operates! It works great in MP, too.

I´m sure that I´ll release a SQF-Version, if I finished my currently project wink_o.gif

Regards,

Mr-Murray

Share this post


Link to post
Share on other sites
@Sickboy

It´s not a problem... because there were some peoples who wanted a solution for this topic and I realized it with a script.

The main thing is, that it operates! It works great in MP, too.

I´m sure that I´ll release a SQF-Version, if I finished my currently project wink_o.gif

Roger wink_o.gif If only the CoC Guys would be ready with NS & Artillery... mmmhh smile_o.gif))

Will have a look at your SQS variant, can probably recode it to SQF within a few minutes, gonna implement it in my mission this weekend so if ur interested I would send it to you smile_o.gif

sry for the offtopic smile_o.gif

Share this post


Link to post
Share on other sites

Ähm... ok that´s great.

But use this versions:

The reamde´s are currently only in German.

But I´m very sure that you´ll understand it wink_o.gif

Singleplayer

Multiplayer

You can find me in ICQ --> Mr-Murray (130...)

Have fun!

Mr-Murray

Share this post


Link to post
Share on other sites

Hey Guys.

To save starting a thread,thought i would post here. smile_o.gif

Currently,over at IC,We are mapping and getting around 110 players turn up for our saturday battle in the tournament.

We are using the revised version of KaRRiLLioN's Vrs.sqf by norrin.

Problem we seem to get is after maybe an hour or so of battling,the Sqf file seems to just stop,causing 55 or so vehicles to completely stop respawning.

Currently,we have tried setting up 14 versions of the script,but we still get at least 3 or 4 sqf's just bug out on us.

The code i'm using is this.

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">

//Here's the updated alternate vehicle respawn script in which the respawn timer only begins counting down when the crew bail.

//Code Sample

/*

//VEHICLE RESPAWN SCRIPT SQF

// Respawns vehicles when they are destroyed, cannot move or cannot fire

// © JUNE 2007 - norrin (norrins_nook@iprimus.com.au), based upon KaRRiLLioN's original vrs.sqf script.

// Version: 2.0

//******************************************************************************************

//***************************

//IMPORTANT: ADD A GAMELOGIC NAMED Server to the mission to prevent multispawn

//To run this script place the following code in the init line of the vehicle:

//v = [this, "vehicle name", x] execVM "vrs_move.sqf"

//where x is the time you wish to set for the vehicle dammaged/destroyed respawn delay

//Note: the vehicle name must be in quotation marks eg. if vehicle name's Hmm1 it must appear in the init line as "Hmm1",

//if you don't want to name your vehicles just put "" in place of the vehicles name

//******************************************************************************************

//****************************

//Start VRS_Move.sqf

*/

private ["_vcl","_respawndelay","_dir","_pos","_type","_run","_delay"];

if (!isServer) exitWith {};

_vcl = _this select 0;

_name_vcl = _this select 1;

_respawndelay = _this select 2;

_dir = Getdir _vcl;

_pos = Getpos _vcl;

_type = typeOf _vcl;

_run = TRUE;

sleep 5;

for [{}, {_run}, {_run}] do

{

while {canMove _vcl || canFire _vcl} do

{

sleep 1;

};

while {!canMove _vcl && count crew _vcl > 0 || !canFire _vcl && count crew _vcl > 0} do

{

sleep 1;

};

_delay = Time + _respawndelay;

while {!canMove _vcl && Time < _delay && count crew _vcl == 0 || !canFire _vcl && Time < _delay && count crew _vcl == 0} do

{

sleep 1;

};

if (!canMove _vcl && Time >= _delay && count crew _vcl == 0 || !canFire _vcl && Time >= _delay && count crew _vcl == 0) then

{

deleteVehicle _vcl;

_vcl = _type createVehicle _pos;

_vcl setVehicleVarName _name_vcl;

_vcl setdir _dir;

sleep 1;

_vcl setvelocity [0,0,0];

_vcl setpos _pos;

sleep 1;

_vcl setvelocity [0,0,0];

sleep 2;

};

};

I have change the code so it makes use of the "if (!isServer) exitWith {};" command,and removing the game logic.

I'm using this code to initialize

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">v = [this, "vehicle", 300] execVM "Respawn\vrs_move.sqf"

Any ideas on this problem?I believe it's just lag as the code works ok when Beta testing with 30 to 40 guys but i could be wrong?

Share this post


Link to post
Share on other sites

Increase the sleep value in the main 'alive' loop so the number of iterations will last longer?

I read someplace that 10k iteration limit was removed, but based on testing a little while back I dont think this is truly the case.

I've noticed sometimes that concurrent executions of a script sometimes screws the variables up between them - like they are sharing the variable space - all I have done so far is randomise the delays to try avoiding conflicts - but I think some better compartmentalisation of variables between script instances might be called for, using array of values (one indexed set of values per script instance) instead of a single variable of shared name between the script instances maybe the way to go to avoid inter-instance variable conflicts?

I know this conflict SHOULDN'T happen, but I have seen it with my own eyes while debugging occasionally.

I am also concerned about Karillion's endless loop with no exit way of doing stuff - is there anywhere any guarantee that such a loop will automatically quit once a map finishes - especially under sqf with execVM?

Have never read that anyplace, so I would tend to assume that some exit strategy is required, and endN boolean that causes it to quit the loop might help matters - the bugs you report saying that processor load up at max might be because you'd run the map a few times already, and previous scripts hadn't terminated?

Food for thought.

Share this post


Link to post
Share on other sites

Seems overly complicated to me. I don't trust the associativity of the && and || commands and would suggest better bracketing. If I've read the code right, this would be a much simpler inner loop (replacing the for)...

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">

while {_run} do

{

//Wait for vehicle to be disabled and crew to be killed

waituntil {(!canMove _vcl or ! canFire _vcl) and count crew _vcl == 0}

sleep _respawndelay;

deleteVehicle _vcl;

_vcl = _type createVehicle _pos;

_vcl setVehicleVarName _name_vcl;

_vcl setdir _dir;

_vcl setvelocity [0,0,0];

};

Share this post


Link to post
Share on other sites
My reasons for SQF:

[*] Precompile at start, then spawn the script instance from memory every time you need it, while SQS get read everytime from your harddrive, even during scriptrun (you can even change scripts while running)! Loading from memory is ALWAYS better IMHO... But it will loan especially when you have many and/or many of the same scripts running/unloaded/loaded etc.

[*] More proper and better overviewable code, you dont have to write all in 1 row like in SQS, but you can use multiple rows for a good logical programming way.

[*] In my eyes a better scripting language logic... the sqs with goto's etc was maybe easy, but too much .bat/basic-ish smile_o.gif I simply prefer the use of waituntil, while, for, switch/case etc... Besides, try to debug an sqs with 10 #points and 30 goto's :P

Also don't forget functions. I don't think we had that ability to put functions inside the same file without having to compile a string.

Share this post


Link to post
Share on other sites

notworthy.gif Thanks for the Help So far guys. notworthy.gif

Rewritten the code without all the check conditions,and only using "Not Alive" command and haven't any problems so far.

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
Sign in to follow this  

×