Jump to content
Sign in to follow this  
Ragnar_Darude

Sleep or WaitUntil?

Recommended Posts

I want to know if anyone has enough insight into the Arma-engine to tell us how to write our scripts in the most efficent way.

When timing is not an issue, which of these two code segments would strain the least on the CPU?

1.

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">for (_i) (_i<=10) (_i=_i+0)

{

    if (anycondition) exitWith {};

    sleep 0.01;

};

or

2.

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

My point is that even if the first example might seem like a more resource friendly one, I do think that the sleep command must use be checked by the game engine every framerate to see if the sleep has finished. Which one is most efficent?

Consider these two examples where i want to wait rhoughly half a minute:

3.

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

and

4.

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">_targettime = (daytime + 0.05);

WaitUntil {daytime >= _targettime};

These two would have different effects if the time is accelerated, but again, which one is more resource friendly?

Share this post


Link to post
Share on other sites

I don't believe there is an appreciable load from either - my experiments have shown that you can run large (thousands) of scripting operations without having an appreciable impact on the framerate.

However, taking your questions at face value....

I believe that waituntil checks its condition every frame like triggers do.

From some of the error reports I've seen, I think that sleep may be just a synonym for waituntil {_time >_start + _delay}

In any case, sleep is at least as lightweight and possibly more so (depending upon implementation) than waituntil.

If you are checking complicated conditions, but don't need to check them every frame, you may wish to use sleep to space things out.

Share this post


Link to post
Share on other sites

I reckon one thing you can safely say is. Sleep is the most efficient way of pausing for a predetermined amount of time.

As for the rest, a lot depends on the circumstance. But out of curiosity, which do you think, from these two. Is the quickest condition to check, from a CPU's point of view?

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">If _ABool Then {};

Or

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">If (_ANum>_BNum) Then {};

Share this post


Link to post
Share on other sites
Quote[/b] ]But out of curiosity, which do you think, from these two. Is the quickest condition to check, from a CPU's point of view?

I may be reading more into your question than you intended but....

Checking a boolean is generally a cheaper operation than comparing two numbers (even ignoring the extra parsing inherent in the second form).

However, boolean variables are normally the result of some relatively expensive calculation (ie, they are unlikely to be static) so you need to take this into account.

Like I say, in the context of the ArmA scripting engine I don't think it's worth trying to second-guess which is the most efficient way of translating a particular test. However, it's just general good practice in any programming environment to hoist invariant code out of loops, yield to other processes when possible, and avoid using the CPU more than you really have to. biggrin_o.gif

Share this post


Link to post
Share on other sites
Quote[/b] ] may be reading more into your question than you intended but....

It was more a general question, about what the sleep command is perceived to do. Sorry, your post wasn't displayed when I made mine.

Quote[/b] ]my experiments have shown that you can run large (thousands) of scripting operations without having an appreciable impact on the framerate.

Of course, but not with every command, every 0.001 seconds. You can bring the game to a grinding halt, with one line of code. I think it helps to try and understand what’s going on, so we can way up the best approach to a specfic problem.

Share this post


Link to post
Share on other sites
Quote[/b] ]Of course, but not with every command, every 0.001 seconds. You can bring the game to a grinding halt, with one line of code.

I don't think it's possible to run commands at a period of 0.001 seconds biggrin_o.gif The way the game seems to work (fairly obviously) is that it updates the game world, renders a frame, then runs a timeslice for any active scripts. Therefore, any descheduling command (sleep or waituntil) will cause a delay of at least one frame. You can't lock up the game by writing

while (true) do {hint "hello"; sleep 0.00000001;}

but you can seriously impact your framerate by writing

while(true) do {for "c" from 1 to 10000 do {hint "hello";} ; sleep 1;} ;

As in any multi-threaded system, the key is to make sure that threads yield often.

Share this post


Link to post
Share on other sites
Quote[/b] ]I don't think it's possible to run commands at a period of 0.001 seconds

Lol...It's possible to run an OFP/Arma script at 0 frames per second smile_o.gif

Share this post


Link to post
Share on other sites

I think sleep 3 is a shorthand version of waitUntil {time > _savedtime + 3} ... like you said.

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

check = 0;

waituntil {if (time < savedtime + 1) then {check = check + 1}; time >= savedtime + 1};

player sidechat str check;

This returns 77 "checks" to see if the condition is met in 1 sec.

Here's a different test that measures something else..

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

myflag = false;

[] spawn {while {myflag} do {addstuff = addstuff + 1}};

myflag = true;

sleep 1;

myflag = false;

player sidechat str addstuff;

addstuff returns 140000. This test also showed me a spawn doesn't execute right away. Notice the flag is set to true after I would have thought the spawn had checked the while loop condition.

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

myflag = false;

[] spawn {while {myflag} do {addstuff = addstuff + 1}};

savedtime = time;

myflag = true;

waituntil {time >= savedtime + 1};

myflag = false;

player sidechat str addstuff;This returned 200000. More CPU cycles given to waituntil?

Share this post


Link to post
Share on other sites
Quote[/b] ]I don't think it's possible to run commands at a period of 0.001 seconds

Lol...It's possible to run an OFP/Arma script at 0 frames per second smile_o.gif

How does a script go forward if speed of the game engine is zero frames per second?

Graphics engine runs at zero FPS but scripting engine doesn't? Is that what you are saying? Isn't ArmA a single-threaded application, which would mean it would not be possible to run for example graphics at zero and scripting at some other rate at the same time.

I have always been thinking about OFP/ArmA scripting that on each frame of the game engine, the scripts are put forward by some amount of code* Then in a single-threaded application this would mean that an FPS of zero means everything is stopped, including every single script that was running. In this it doesn't matter if you can make "multi-threaded" scripting, as it is actually all happening inside one operating system thread, which containts the whole game, as I have understood it to be in the case of OFP & ArmA. But then again I am not a game developer, especially not a game developer working at BIS, who would be best to shed light into these ponderings.

Could you please explain what did you mean.

* I recall some talk that in OFP about 100 lines of code could be the amount which is processed at one time but I'm not sure of this, I don't remember who said that or was it 100 or 1000 LOL... and was it that this amount would be processed per frame or was it just a 'blob' of code, and the game would try to execute as many of these 'blobs' per frame as possible. Anyway, the faster the game is running the more relative time you can give for executing scripts is not a bad guess I think, as then the game wouldn't slow down too much. This means in my understanding that the FPS really can affect game logic too, not just visual experience. So a computer which can't run the game at high FPS could have 'even more stupid AI' than on faster computers.

Share this post


Link to post
Share on other sites

while {true} do

{

call {....};

sleep 1;

};

but i like use this:

_t=time-1;

waituntil

{

if (time -_t >= 1) then {call {...}; _t = time};

true

};

i'am thing there is more fps..

Share this post


Link to post
Share on other sites
Quote[/b] ]Could you please explain what did you mean.

I'm definitely thinking back to found memories, of loosing half my work, because I forgot to add one simple command to a script, when running fullscreen sad_o.gif But my point is, the whole concept of time, as measured by the game. Only helps to confuse things in this context.

My original opinion still stands, having a better understanding helps tackle specific problems. This thread is a good example, which sbsmac is already aware of.

Ok, it's true the majority of people won't encounter this kind of problem. Not everyone wants to run 110 player servers. But for anyone who wants to push the game as far as they can, it's a valid topic for discussion.

But getting back to measuring game time e.t.c You can execute a line of code 9,999 times and it won't register on the game clock at all:

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

_MyTime=Time;

While {_Count<9999} Do

{

_Count=_Count+1;

};

Player SideChat Format ["Time %1",Time-_MyTime];

So arguing over whether you can run a script at exactly 0.001 seconds is kind of missing the point. It's possible, to seriously effect the games performance, with scripts alone.

As you say, second guessing the game might not be much help. But being able to make informed decisions, based on the kind of tests Doolittle posted. Is hardly going to be detrimental to anyone?

Share this post


Link to post
Share on other sites

UNN - we seem to be arguing over something where we are largely in agreement! ;-)

BTW - I tried Doolittles tests and saw absolutely no difference between sleep and waituntil (as expected). The test is interesting for a couple of reasons though:-

1) I would have expected the while loop to completely lock up the machine but it doesn't.

2) Running the script a few times gives me numbers which vary with a granularity of 10K - so 'while' must deschedule at this number of interations.

Quote[/b] ]It's possible, to seriously effect the games performance, with scripts alone.

Of course it is -my point is just that worrying over whether to use sleep vs waituntil for a simple condition is pointless - far better to concentrate on what is inside the bodies of your loops and to ensure that they yield reasonably often, eg by placing a 'sleep 0.001' inside cpu-bound section. This will enable the rest of the game engine to run.

Quote[/b] ]But getting back to measuring game time e.t.c You can execute a line of code 9,999 times and it won't register on the game clock at all:

That's not really surprising is it ? Think of arma.exe as running this kind of loop :

while (true) {

1) render frame (not needed for server)

2) update game-state

3) run each script until reach descheduling point

}

Game time will be set at step 2 so you will not see any change within a single context-switch of a script. Scripts do not magically run in parallel with the rendering engine, gracefully siphoning off some percentage of CPU, they use all the CPU available until they deschedule. _That's_ why writing loops that iterate 10K times wihtout any yielding is a bad idea - it has nothing to do with the difference between waituntil and sleep !

Share this post


Link to post
Share on other sites
Quote[/b] ]1) I would have expected the while loop to completely lock up the machine but it doesn't.  

2) Running the script a few times gives me numbers which vary with a granularity of 10K - so 'while' must deschedule at this number of interations.

Yeah, the While loop used to just terminate after 10,000 cycles in previous versions of Arma. It was changed recently.

Quote[/b] ]it has nothing to do with the difference between waituntil and sleep !

Considering those two commands is as good a place to start as any. It's a subject that comes up on numerous occasions, only it used to be the @ command in OFP, instead of WaitUntil. Ok, you might not think it’s the most important question, but it’s still a valid question.

Share this post


Link to post
Share on other sites

I really don't get the point so far...

I replaced all my waitUntil with while loops.

For example:

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

waitUntil {(unitReady _searcher || !alive _searcher)};

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

while {((!unitReady _searcher) && (alive _searcher))} do {

sleep 1;

};

But to me it sounds like there's no different between thouse two codes? crazy_o.gif

But Doolittle sad: "while" gives 140000 CPU cycles and "waitUntil" gives 200000 CPU cycles so a while loop is more CPU friendly. Right?

Share this post


Link to post
Share on other sites

The two variants you provide have different behaviour.

Waituntil will check every frame.

The while loop you provided sleeps for a second each iteration so the latency in detecting the change in condition is up to 1 second vs 1 frame for the waituntil.

You can make the two forms roughly equivalent by setting the sleep period to 0.001 (say).

I don't think it's worth worrying about - waituntil has a much clearer syntax in the case where you are genuinely waiting for some conditions to be met. (The exception might be where you have a very complicated condition that requires a load of processing, where you might wish to only perform the check once a second or so.)

Quote[/b] ]

But Doolittle sad: "while" gives 140000 CPU cycles and "waitUntil" gives 200000 CPU cycles so a while loop is more CPU friendly. Right?

Try running the tests for yourself - I did and noticed no difference in performance. One has to be careful in any case when analysing these kind of low-level performance results since they are so easily perturbed by environmental or transitory factors.

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  

×