Jump to content
Sign in to follow this  
galzohar

Efficiency question: sleep vs waitUntil

Recommended Posts

Is there any difference in how efficient these 2 commands are? That is, for example, is there a major difference between these 2 (ignore syntax errors plz):

_startTime = time;
waitUntil {_startTime + 100 > time};

sleep 100;

I don't mean if there's a small difference because of variable use or whatever, but rather if there is a major difference between these 2. Just wondering so I know if I should avoid loops with sleep and replace them with waitUntil where I can, or do it the other way around (replace waitUntil with sleep where possible). To know that I need to know which work better, which depends on how the engine implements them behind the scenes...

Anyone knows?

Share this post


Link to post
Share on other sites

waitUntil

will check the condition as fast as the game possibly can, which may lock your game.

the sleep command will wait x seconds letting other things run along nicely.

As far as my experience go you should never do a loop without putting a sleep in it.

i.e.

IMHO incorrect

while{true} do{
   //stuff
};

Correct way

while{true} do{
   //stuff
   sleep 0.01;
};

You can sleep the waitUntil as follows

waitUntil{
   sleep 10;
(something=="ROFL")};

Note that you don't have a ; after the condition, because its treated as a function with a return value.

This is untested but I think that's how the waitUntil sleep is done, correct me if wrong,

This will check the condition every 10;th second.

[edit]

So I forgot about the different uses of loops compared to waitUntil

I think you should avoid sleeping waitUntil and use that command if you want to check something really really fast, for example if a script is ready.

In the other cases you should use either for-loops or while-loops, with sleeps mind you :)

Edited by Taurus

Share this post


Link to post
Share on other sites

waitUntil runs the code / checks the condition once every frame.

while will continuesly run the code, unless sleep is used. (Altough, since ArmA2, if the loop runs in a spawned scripted instance, instead of called from an event, the scheduling of these scripts seems to be unpredictable)

you can not sleep shorter than 1 frame; sleep always sleeps at least 1 frame, thus sleep 0.001 in most situations would be 1 frame, depending on your fps.

"sleep 1" afaik is nothing more than; _endTime = time + 1; waitUntil {time > _endTime};

This feeling is strengthened by the JIP process, where time starts at 0 when joining the server, and time suddenly syncs with the server (usually massively increasing time).

If you try to "sleep 30" in an init script, but if the server mission already ran longer than 30 seconds, the sleep ends and the script will continue, even though no real 30 seconds have passed ;)

Personally I use while and for loops incase I don't need to sleep, or incase I do need to sleep longer than 1 frame.

waitUntil is a perfect solution imo for loops that must track something, for instance;

A tracer round that must follow the real bullet, it would move 'jerky' if you used too big sleep, and depending on FPS this effect is worse,

if you use a waitUntil loop (though could aswell use sleep 0.001 in a while or for loop), it will be smooth.

@Taurus; The line termination is a myth, something for a very long time I misunderstood aswell :D

waitUntil { sleep 1; test == 1; };

Will work just as good as

waitUntil { sleep 1; test == 1 };

same with functions, there is no difference in operation, only in syntax;

test =
{
  _this * 2
};

or

test =
{
  _this * 2;
};

Edited by Sickboy

Share this post


Link to post
Share on other sites

If you need to suspend a script for a specific amount of time, use sleep. You should only use waitUntil if you don't know how long to suspend the script. I'd imagine using sleep will be much better on performance than a waitUntil loop.

---------- Post added at 10:26 AM ---------- Previous post was at 10:22 AM ----------

@Taurus; The line termination is a myth, something for a very long time I misunderstood aswell :D

waitUntil { sleep 1; test == 1; };

Will work just as good as

waitUntil { sleep 1; test == 1 };

same with functions, there is no difference in operation, only in syntax;

It may work fine, but for the sake of others trying to understanding your code, not terminating with a semicolon makes it easier to identify the expression as a return value.

Share this post


Link to post
Share on other sites

Depends. If all your functions return a value, which actually they do (the outcome of the last ran statement, usually nil), then there is no need to denote the last line to be returning code, as it is a given :)

Personally I have been using the method without ;, but Spooner won me over to rather stick to ending all statements with ;

which does make sense to me.

Edited by Sickboy

Share this post


Link to post
Share on other sites
It still looks better IMO to leave the last expression without a semicolon. :j:
IMO just depends what you are used to :)

Anyway, to each their own coding methods. It's a bit like believes/bibles and thus a minefield :D

As to the sleep and waitUntil usage, it really just depends on the requirements of your project/script. But agreed, in most cases, a loop with sleep will be sufficient.

Share this post


Link to post
Share on other sites
As to the sleep and waitUntil usage, it really just depends on the requirements of your project/script. But agreed, in most cases, a loop with sleep will be sufficient.

The original question was which is more efficient: A simple sleep or a waitUntil loop. I can't imagine a waitUntil loop being more effecient than a sleep.

Share this post


Link to post
Share on other sites

The answer to his original question is yes, there is a difference in efficiency, even though probably not measurable.

The reason is that he does the startTime + 100 calc every iteration in the waitUntil loop.

If he would use: _endTime = time + 100; waitUntil { time > _endTime };

then there is no difference in efficiency. Only a lot more to type :)

Share this post


Link to post
Share on other sites

I didn't ask which kind of *loop* was more efficient, but which command was more efficient, and according to what you guys are saying both are checked every frame and thus are the same efficiency.

Obviously something that runs every second will be faster than something that runs every frame, but that was not my question ;)

Share this post


Link to post
Share on other sites

If I'd created the sleep command, it'd be more efficient because you say "sleep 10" and it forgets about your script until it's reminded by a scheduler. Using waitUntil would generate comparisons every frame.

So I prefer sleep thinking pros code like noobs llike me!

Share this post


Link to post
Share on other sites

Actually, Kronzky did some checking, and wasn't able to verify any performance degradation:

I ran over 500 concurrent waitUntils (even without any sleep delays in them), and noticed hardly any performance degradation

That made me curious, so I tested myself. I actually found that using waitUntil was more efficient for my purposes and cleaner in code. I think the game engine manages the checking dynamically.

I'm not entirely convinced it HAS to check every frame. It may do, but I haven't noticed any performance problems so it is leading me to believe it manages checking in such a way to ensure performance impacts are minimal.

Edited by Rocket

Share this post


Link to post
Share on other sites

Except that thread is Arma 2 and doesn't provide any factual answers (only theories, which I could've made up myself).

All I really need to know is whether or not sleep and waitUntil both check the condition every frame or whatever, but it seems only BIS has the definite answer...

A possible way to test this might be to make the 2 experiments:

1. Run a massive amount of scripts that simply do "sleep 1000"

2. Run an equally massive amount of scripts that do "waitUntil {false}"

And measure if there is any difference in the FPS hit. I'm not sure if this would actually provide too useful answers though.

Edited by galzohar

Share this post


Link to post
Share on other sites
Altough, since ArmA2, if the loop runs in a spawned scripted instance, instead of called from an event, the scheduling of these scripts seems to be unpredictable

Thank you :D

I was wondering what was going on with this. I have a script that spawns up to several hundred small scripts and after a while I experience what I previously thought of as "script lag" :)

I considered raising it as a bug but I wasn't sure if it was a scheduling mechanism working as it should.

---------- Post added at 01:21 AM ---------- Previous post was at 01:18 AM ----------

Actually, Kronzky did some checking, and wasn't able to verify any performance degradation:

That made me curious, so I tested myself. I actually found that using waitUntil was more efficient for my purposes and cleaner in code. I think the game engine manages the checking dynamically.

I'm not entirely convinced it HAS to check every frame. It may do, but I haven't noticed any performance problems so it is leading me to believe it manages checking in such a way to ensure performance impacts are minimal.

Unless the scripting code is far more advanced than I would suppose, I suspect that a Sleep command is checked as often as a waitUntil. In fact I would imagine that it's exactly same mechanism when skinned out of it's scripting skin ;)

Share this post


Link to post
Share on other sites
That made me curious, so I tested myself. I actually found that using waitUntil was more efficient for my purposes and cleaner in code. I think the game engine manages the checking dynamically.

I'm not entirely convinced it HAS to check every frame. It may do, but I haven't noticed any performance problems so it is leading me to believe it manages checking in such a way to ensure performance impacts are minimal.

I would guess that waitUntil uses some kind of interrupt to remove the block. I'm going to guess its NOT an OS level interrupt, but the game could still handle them in an efficient manner, either by handling them in a different thread, or throwing them in with the trigger checks it already does (which is what I'm assuming it does). Yes there could be a background loop somewhere, but that's the mission designer's fault, either through laziness or lack of understanding of how to handle events.

Lets say I'm waiting for some specific thing to happen (only once). Well, I can either write a nasty polling loop like:

while(true) do{
    if(something == 30) { //do stuff };
    sleep 100;
}

or I can write:

waitUntil{ something == 30; }

inside of my function. This has many advantages, including that I'm no longer running a poll in the background, something that would be left over otherwise, which would cause more problems than just doing a little waitUntil. Its also near instant when something equals 30; I don't have to wait until the next time the loop polls.

If I need to consistently check for something then perform some logic, I just put it waitUntil inside a loop:

while(true) do{
   waitUntil{ something == true; }
   //stuff
   something = false;
}

That way the loop is blocked completely until something is true. To me that is much more efficient than sleeping with an if statement inside your loop.

Share this post


Link to post
Share on other sites

I sort of came to the conclusion, that so long as I used each function correctly, and structured my code "good", it didn't really matter which was more efficient as I needed to use so many of them before it had a noticeable impact.

I use waitUntil if I want to suspend a script until something happens, mainly because that's what the command was created for. I use while loops for more complex interrogation with either complex conditions and/or operations.

Share this post


Link to post
Share on other sites
I sort of came to the conclusion, that so long as I used each function correctly, and structured my code "good", it didn't really matter which was more efficient as I needed to use so many of them before it had a noticeable impact.

Exactly, and that was kind of the point I was trying to make. Its all about how you structure your code, which is pretty standard across the board for programming.

So who wants to start writing the book "ArmA 2 Design Patterns" destined to be published by O'Reilly. ;) (If only...)

Share this post


Link to post
Share on other sites

I think you're splitting hairs if the check in the waitUntil is a relatively easy operation

I'd imagine that a sleep has the game checking every frame if time > (oldTime + sleepTime) then going its merry way whereas a waitUntil of someBool == someOtherBool or a waitUntil of someNumber < anotherNumber is going to be doing the same damn thing (as sleeping) every frame.

Edited by Bellicosity

Share this post


Link to post
Share on other sites

I just realized I was missing the point and it derailed this topic, I'm terribly sorry.

Bellicosity is absolutely correct.

sleep x is way better than pausing scripts with waitUntil

Share this post


Link to post
Share on other sites
Except that thread is Arma 2 and doesn't provide any factual answers (only theories, which I could've made up myself).

And why would you think that ArmA2 would implement this significantly differently from ArmA1? As for theories, well, by definition the only people who can tell you what is in BIS's code are BIS but at least my theories are informed by some practical experience with implementing schedulers and VM's :-)

I'm prepared to bet you a virtual doughnut that if you ever get confirmation from BIS about the low-level implementation of waitUntil, it will accord with my theories :-P And in case you missed it in the original thread, yes I _did_ do some measurements to check them.

I would guess that waitUntil uses some kind of interrupt to remove the block. I'm going to guess its NOT an OS level interrupt, but the game could still handle them in an efficient manner, either by handling them in a different thread, or throwing them in with the trigger checks it already does (which is what I'm assuming it does).

Here goes my second virtual doughnut....

You are almost certainly wrong. The exit condition for waitUntil is clearly dynamic (ie, it can change every time you evaluate it). You can't have some kind of background interrupt handler firing on on a complex dynamic condition. All you can do is test it frequently to see what has changed (ie polling). The only real question of implementation is whether you do that polling inside the VM environment (scripting engine) or try to do it as a 'native' operation outside of the environment. Given the completely arbitrary nature of Waituntil exit conditions (function calls are allowed) I'll bet that all waituntil does is deschedule the current script until the next frame, whereupon the exit criterion is tested again by rerunning the script commands that comprise it.

Oh, and for the sake of consistent implementation, I'd be very surprised if sleep wasn't just a synonym for _now=time; waituntil {time > _now+delay}. :-)

And to answer the very first post.... Really, don't worry about it. The engine is pushing around millions of polygons a second and moving (potentially) thousands of simulated entities. Optimisation at the level you are looking at is pointless :-)

Share this post


Link to post
Share on other sites

Speaking as a noob, my idea for a scheduler is way more efficient than that.

And, one of the biggest changes for servers in Arma2 was to introduce strict scheduling - so there is a scheduler.

:P

Share this post


Link to post
Share on other sites

So far it seems like it makes the most sense that both are equivalent (as in, checked every frame), so there is no reason to avoid using waitUntil unless the condition is extremely complex to calculate.

Speaking of scheduling, I still wonder how the engine handles stuff like 2 different scripts doing i=i+1 (where i is global)... In a standard windows program you'd need to use some kind of mutex if you want to be sure your operation is safe, but what about Arma 2 scripting? I suppose that could be tested by running a very large amount of scipts, each performing i=i+1 a large amount of times, and then seeing if the end result is as expected (assuming i doesn't go above its maximum allowed value).

Share this post


Link to post
Share on other sites

All of you are on your own thinking it makes more sense to check a sleep command every frame :D

Share this post


Link to post
Share on other sites
All of you are on your own thinking it makes more sense to check a sleep command every frame :D

Well if you can show it's being done differently, I'd love to see how.

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  

×