question for pros: wait / wait randomly
Moderators: Moderators for English X Forum, Scripting / Modding Moderators
question for pros: wait / wait randomly
I'm wondering whether some lag/freeze/ctd problems are due to scripts forced to wait.
What I'm trying to say is this:
There are many game scripts necessary to play X3. Some scripts run permanently, some run only when triggered, others only once when starting the game or loading a savegame.
However, only one single script can run at a time.
Therefore scripts contain wait commands which divide in two groups: deterministical like '@wait 20 ms' and statistical like '@wait randomly between 10 ms and 50 ms'.
So if one script is ''waiting'' another script can run until it 'hits' the wait command, which enables another script to continue, and so forth...
In the optimum case there may be intervals where no script is running (all in wait states) and intervals where precisely one script is running (all others are waiting). But, of course, this is not the reality.
Most of the time several scripts are 'awake' and willing to run. But since only one of them can run at a time the others are forced to wait, building up as a ''heap'' over time.
I'm not a computer/software expert so I do not know what this ''forced wait state'' means in terms of game play. However my guess is that it shows as lag and, depending on the size of the ''heap'', can lead to freeze or even ctd.
What do you think?
Cheers Euclid
What I'm trying to say is this:
There are many game scripts necessary to play X3. Some scripts run permanently, some run only when triggered, others only once when starting the game or loading a savegame.
However, only one single script can run at a time.
Therefore scripts contain wait commands which divide in two groups: deterministical like '@wait 20 ms' and statistical like '@wait randomly between 10 ms and 50 ms'.
So if one script is ''waiting'' another script can run until it 'hits' the wait command, which enables another script to continue, and so forth...
In the optimum case there may be intervals where no script is running (all in wait states) and intervals where precisely one script is running (all others are waiting). But, of course, this is not the reality.
Most of the time several scripts are 'awake' and willing to run. But since only one of them can run at a time the others are forced to wait, building up as a ''heap'' over time.
I'm not a computer/software expert so I do not know what this ''forced wait state'' means in terms of game play. However my guess is that it shows as lag and, depending on the size of the ''heap'', can lead to freeze or even ctd.
What do you think?
Cheers Euclid
well, the way scripts work, is pretty much the same as how multi tasking works
waits rn't the only commands that allow other scripts to run, theres various commands that add interupts
any freeze or lag is due to the game engine not updaing quick enough or getting blocked, so even if all scripts were made to wait, the game engine still gets updated and rendered.
its the lack of waits that causes the freezeing, as the engine is trying to process the whole script and cant move on until it hits an interupt
waits rn't the only commands that allow other scripts to run, theres various commands that add interupts
any freeze or lag is due to the game engine not updaing quick enough or getting blocked, so even if all scripts were made to wait, the game engine still gets updated and rendered.
its the lack of waits that causes the freezeing, as the engine is trying to process the whole script and cant move on until it hits an interupt
So essentially you agree?Cycrow wrote: ........its the lack of waits that causes the freezeing, as the engine is trying to process the whole script and cant move on until it hits an interupt
If my 'hypothesis' is correct then it would make some sense trying to optimize the wait commands in all scripts.
Cheers Euclid
Generally, the more interrupts and waits you throw into a script, the less likely it is to cause game freezing problems. (because the nicer it will play with its fellow scripts)
When I'm designing a script, I usually like to set some minimum threshold of performance to the script, such that the user won't think it's taking too long. Then I put in as many waits as possible without compromising that minimum level of performance.
Said another way, if the user won't care if it takes 5 seconds or 0.01 seconds for a particular section of code to execute, make it slower. Prevents one script from monopolizing the cpu. If it's important that a piece of code runs quickly, by all means don't put a wait in that section.
Note that loops are really the only place you absolutely need to use waits. Sequential code just isn't going to be long enough to notice any run time. It's only iteration where you can get yourself in trouble.
Cheers.
When I'm designing a script, I usually like to set some minimum threshold of performance to the script, such that the user won't think it's taking too long. Then I put in as many waits as possible without compromising that minimum level of performance.
Said another way, if the user won't care if it takes 5 seconds or 0.01 seconds for a particular section of code to execute, make it slower. Prevents one script from monopolizing the cpu. If it's important that a piece of code runs quickly, by all means don't put a wait in that section.
Note that loops are really the only place you absolutely need to use waits. Sequential code just isn't going to be long enough to notice any run time. It's only iteration where you can get yourself in trouble.
Cheers.
"Nature's first green is gold" . . . stay golden.
initialization scripts (setup/init/al.plugin) -> dont use waits .. these scripts wait for the previous to finish before the next runs ..(make them short and simple)
other scripts -> it cant hurt to put in an extra wait .. (it may not be needed .. and could even make your script 'slow' .. but it cant 'hurt' .. not having them in there could hurt your game much more ..)
G
other scripts -> it cant hurt to put in an extra wait .. (it may not be needed .. and could even make your script 'slow' .. but it cant 'hurt' .. not having them in there could hurt your game much more ..)
G
Thanks for the input, guys.
Still there are some open questions.
-----------------------------------------------------------
-----------------------------------------------------------
What is still unclear to me: What happen if several scripts are not in a wait state (nor interrupted)?
Since only one can run at a time: who/what decides which runs first? What are the others doing (forced wait) during that time?
What you guys said above refers to one script. What I'm trying to find out is the balancing of wait states in each script taking into account all permanently runnig scripts.
Cheers Euclid
Still there are some open questions.
-----------------------------------------------------------
What is the difference between a 'wait' and an 'interrupt' command?Burianek wrote: Generally, the more interrupts and waits you throw into a script, the less likely it is to cause game freezing problems......
When do they run? If you starting X3 or if you load a savegame? Also what determines the hierarchy (which runs first, second etc..)Red Spot wrote: initialization scripts (setup/init/al.plugin) -> dont use waits .. these scripts wait for the previous to finish before the next runs ..
-----------------------------------------------------------
What is still unclear to me: What happen if several scripts are not in a wait state (nor interrupted)?
Since only one can run at a time: who/what decides which runs first? What are the others doing (forced wait) during that time?
What you guys said above refers to one script. What I'm trying to find out is the balancing of wait states in each script taking into account all permanently runnig scripts.
Cheers Euclid
-
- Posts: 3
- Joined: Wed, 26. Oct 05, 15:32
First of I want to say that I'm not an experienced X3 scripter so this might be completely irrelevant.
However from a general programming standpoint:
The X3 engine keeps track of all the running processes (scripts). This is done by a scheduler, there are many
types of schedulers. According to the MSCI handbook X2 uses a scheduling scheme called "cooperative multitasking".
This means that the scheduler can’t interrupt a running process by itself, it has to wait for the running process to
release control, i.e. execute a wait command. It can then look at all the processes currently wanting to execute ("forced wait") and choose one to hand over control to.
So how does it choose which process to hand over control to? Most likely (and this is where the guesswork comes in) it is based on priorities.
The main game processes (graphics rendering, AI, collision detection etc) will have a high priority and if any of them want to execute they are given control. Only if no high priority process wants to execute will control be handed to lower priority processes (scripts), it will then most likely choose the script that has been waiting to execute the longest.
This means (if I’m correct) that there’s no reason to worry about lagging the game by using wait.
However excessive use of wait will lead to a lot of context switches (switches between processes) which of course do take up some cpu time. So its probably not a good idea to place a script like this on every object in the game.
while(true) wait(very short time)
However from a general programming standpoint:
The X3 engine keeps track of all the running processes (scripts). This is done by a scheduler, there are many
types of schedulers. According to the MSCI handbook X2 uses a scheduling scheme called "cooperative multitasking".
This means that the scheduler can’t interrupt a running process by itself, it has to wait for the running process to
release control, i.e. execute a wait command. It can then look at all the processes currently wanting to execute ("forced wait") and choose one to hand over control to.
So how does it choose which process to hand over control to? Most likely (and this is where the guesswork comes in) it is based on priorities.
The main game processes (graphics rendering, AI, collision detection etc) will have a high priority and if any of them want to execute they are given control. Only if no high priority process wants to execute will control be handed to lower priority processes (scripts), it will then most likely choose the script that has been waiting to execute the longest.
This means (if I’m correct) that there’s no reason to worry about lagging the game by using wait.
However excessive use of wait will lead to a lot of context switches (switches between processes) which of course do take up some cpu time. So its probably not a good idea to place a script like this on every object in the game.
while(true) wait(very short time)
witty text here
waits and interupts r simlar, the main difference, is that a wait will halt the script until the wait time has elapsed, whereas an interupt just lets other scripts run but will return back to that script as soon as the queue is free.
when running multiple scripts, the scripts are put on a stack, the first one on the stack is run until it gets to an inturpt point, then the next one is run, and so on eventually returning back to the interup points to run the rest of the scripts
you just gotta remember it works the same way as windows does to run multiple programs, althou it appears you running ltos of programs, windows is only ever processing one program at a time
it just breaks the programs into blocks and process small chunks at a time to make it appear that multiple programs are running
when running multiple scripts, the scripts are put on a stack, the first one on the stack is run until it gets to an inturpt point, then the next one is run, and so on eventually returning back to the interup points to run the rest of the scripts
you just gotta remember it works the same way as windows does to run multiple programs, althou it appears you running ltos of programs, windows is only ever processing one program at a time
it just breaks the programs into blocks and process small chunks at a time to make it appear that multiple programs are running
euclid wrote:When do they run? If you starting X3 or if you load a savegame? Also what determines the hierarchy (which runs first, second etc..)Red Spot wrote: initialization scripts (setup/init/al.plugin) -> dont use waits .. these scripts wait for the previous to finish before the next runs ..
they run when you start/load a game .. each and every time ..
what the exact hierarchy is I dont know ..
afaik it starts with the 'init....' onces (wich we should never need to use .. )
than the 'setup....' and 'al.plugin.....' onces but wich of the 2 comes first I dont know (doesnt really matter anyway)
the hierarchy within the 'group' is alfabetical order .. (you wanna mess up your custom commands .. install a script called "setup.AAAAAA" and make it a never ending loop ... ......)
and as these type of scripts are there to set things up they should be able to run at the start of a game .. (not 5 minutes in game .. or so)
so you should take care to make your setup/al.plugin script runs quickly so any other setup/al.plugin script can be run ..
if you do feel the need your setup scripts needs to do much wich you cant 'rush' .. than you could run a script on 'null' (I pers. however try to avoid this as I have nothing to 'simply' interfear with that task once it runs)
G
You can delete it by pressing del in the list of global tasks in the script console, but not much help in the scripting engine, that's trueRed Spot wrote: if you do feel the need your setup scripts needs to do much wich you cant 'rush' .. than you could run a script on 'null' (I pers. however try to avoid this as I have nothing to 'simply' interfear with that task once it runs)
G
- nuclear_eclipse
- Posts: 1129
- Joined: Thu, 2. Sep 04, 01:54
Scripts in X3 function almost exactly like multi-threaded Java programs, which also run on the 'cooperative multitasking' methodology (although the Java Runtime Environment actually uses cooperative forms for multiple threads of a single program and forced form between multiple Java programs).
One thing to always keep in mind is that the '@=wait XX ms' command has one major property, as with all high-level languages. The wait command will halt execution for AT LEAST xx milliseconds. It's quite possible for the script to request a 1ms wait and not receive execution again until at least 20ms or so due to the number of scripts on the stack.
The execution wait period is never guaranteed for anythin except a minimum wait period, and your script should NEVER rely on waiting for that minimum time. However, the accuracy of waits will increase as the length of the wait increases, but that is simply because by the time the wait expires, the script has longer time to reach the top of the execution stack, so has a better chance of being called again once the wait period expires.
In all, the only true way to wait for an EXACT period of time is to write a program in assembly language and have that runas the only program on the CPU. Only then can you guarantee an exact wait period, as you have total controll over processor flow. Since X3 scripts are about as far away from this situation as possible, the best we can ever hope for is a minimum wait time.
---
@wait xx ms - vs - @wait randomly between xx and yy ms
Based on the type of system we are working with, the only true reason to use the random form is to add a bit of 'natural' feel to the script if it is being used closely by the user. So if you want something to happen every so often, but not on a exact schedule, use the random wait. Otherwise, just use a normal wait. It's less taxing on the processor (no random # generating all the time) and it makes your script much more predictable.
---
As for how to waits to keep the engine running smoothly, I have found that at least having a 1ms wait for every 10 lines of code helps to keep my system running more smoothly, but this is only noticeable when there is a LOT of scripts on the stack that are constant-running scripts.
In general, I use a 10ms wait if I am just sticking a wait in to break up a piece of code. If I'm waiting on something to happen in the universe, like a ship docking, hotkey press, etc, I at least use a 80-100ms wait, as a tenth of a second seems instantaneous enough to most users. If the waiting routine is even less necessary, such as a background task,I will sometimes use 500ms waits or longer, depending on how important the task is.
---
I would basically say that as long as you have any sort of wait in your program, especially during loops, you will be just fine. I sincerely doubt that the use (or misuse) of waits really causes any of the bugs with autopilot or such. I personally think that is something based on the engine code itself.
One thing to always keep in mind is that the '@=wait XX ms' command has one major property, as with all high-level languages. The wait command will halt execution for AT LEAST xx milliseconds. It's quite possible for the script to request a 1ms wait and not receive execution again until at least 20ms or so due to the number of scripts on the stack.
The execution wait period is never guaranteed for anythin except a minimum wait period, and your script should NEVER rely on waiting for that minimum time. However, the accuracy of waits will increase as the length of the wait increases, but that is simply because by the time the wait expires, the script has longer time to reach the top of the execution stack, so has a better chance of being called again once the wait period expires.
In all, the only true way to wait for an EXACT period of time is to write a program in assembly language and have that runas the only program on the CPU. Only then can you guarantee an exact wait period, as you have total controll over processor flow. Since X3 scripts are about as far away from this situation as possible, the best we can ever hope for is a minimum wait time.
---
@wait xx ms - vs - @wait randomly between xx and yy ms
Based on the type of system we are working with, the only true reason to use the random form is to add a bit of 'natural' feel to the script if it is being used closely by the user. So if you want something to happen every so often, but not on a exact schedule, use the random wait. Otherwise, just use a normal wait. It's less taxing on the processor (no random # generating all the time) and it makes your script much more predictable.
---
As for how to waits to keep the engine running smoothly, I have found that at least having a 1ms wait for every 10 lines of code helps to keep my system running more smoothly, but this is only noticeable when there is a LOT of scripts on the stack that are constant-running scripts.
In general, I use a 10ms wait if I am just sticking a wait in to break up a piece of code. If I'm waiting on something to happen in the universe, like a ship docking, hotkey press, etc, I at least use a 80-100ms wait, as a tenth of a second seems instantaneous enough to most users. If the waiting routine is even less necessary, such as a background task,I will sometimes use 500ms waits or longer, depending on how important the task is.
---
I would basically say that as long as you have any sort of wait in your program, especially during loops, you will be just fine. I sincerely doubt that the use (or misuse) of waits really causes any of the bugs with autopilot or such. I personally think that is something based on the engine code itself.
The only caveat I'd add to this is if you have a bunch of scripts that initialize and start some loop upon game load or some such, you might want to use wait random. If you use the regular wait, you might get multiple instances of the same script all trying to execute at the same moment every time the loop completes. It's probably better to let these stagger, so using random waits will distribute execution evenly over time.nuclear_eclipse wrote:@wait xx ms - vs - @wait randomly between xx and yy ms
Based on the type of system we are working with, the only true reason to use the random form is to add a bit of 'natural' feel to the script if it is being used closely by the user. So if you want something to happen every so often, but not on a exact schedule, use the random wait. Otherwise, just use a normal wait. It's less taxing on the processor (no random # generating all the time) and it makes your script much more predictable.
(does that make sense? don't feel like I explained that very well)
"Nature's first green is gold" . . . stay golden.
Nuclear_eclipse, that was very interesting, thanks for the briefing.
So there is a chance that stacked scripts cause lag.
I'm not saying that bugs like the auto pilot are related to that. But what makes some sense to me (now) is that the amount of lag (or smootheness) varies with the savegame.
For example Ore Belt. I always had heavy lag there but at one stage I've decided to save there, fought a battle and died. Reloaded and the lag was almost gone.
We know that the savegame contains also the scripts and one would expect that they are precisely in the state when the game was saved. However it seems that saving a game and reloading reshuffles the 'stack' .
Does this make sense?
I think there is an issue here. It should be possible to optimize the wait commands in a hollistic way (taken into account all running scripts).
Burianek is right in saying ....
Cheers Euclid
So there is a chance that stacked scripts cause lag.
I'm not saying that bugs like the auto pilot are related to that. But what makes some sense to me (now) is that the amount of lag (or smootheness) varies with the savegame.
For example Ore Belt. I always had heavy lag there but at one stage I've decided to save there, fought a battle and died. Reloaded and the lag was almost gone.
We know that the savegame contains also the scripts and one would expect that they are precisely in the state when the game was saved. However it seems that saving a game and reloading reshuffles the 'stack' .
Does this make sense?
I think there is an issue here. It should be possible to optimize the wait commands in a hollistic way (taken into account all running scripts).
Burianek is right in saying ....
That is one general rule of optimizing the smootheness of the game play......if you have a bunch of scripts that initialize and start some loop upon game load or some such, you might want to use wait random. If you use the regular wait, you might get multiple instances of the same script all trying to execute at the same moment every time the loop completes. It's probably better to let these stagger, so using random waits will distribute execution evenly over time.
Cheers Euclid
it should be noted that certain events can cause waits to end prematurely.
For example, in X2 I noticed that the player changing sectors would cause this, as would viewing the trade menu(d) of a player owned station. In these cases, a script continued as though it had completed it's wait.
I suspect, though I haven't checked, that loading the game has a similar effect.
For example, in X2 I noticed that the player changing sectors would cause this, as would viewing the trade menu(d) of a player owned station. In these cases, a script continued as though it had completed it's wait.
I suspect, though I haven't checked, that loading the game has a similar effect.
- nuclear_eclipse
- Posts: 1129
- Joined: Thu, 2. Sep 04, 01:54
This is correct. Simply selecting a ship that is currently running a wait command and going into the command console can abort a currently running wait. (I think) At any rate, you should plan that regular wait commands can and will get interrupted. If you want to make sure that your waits are never interrupted, it's easy, do this:moggy2 wrote:it should be noted that certain events can cause waits to end prematurely.
For example, in X2 I noticed that the player changing sectors would cause this, as would viewing the trade menu(d) of a player owned station. In these cases, a script continued as though it had completed it's wait.
I suspect, though I haven't checked, that loading the game has a similar effect.
Code: Select all
021 $wait.time = = random value from 480000 to 600000 - 1
022 while $wait.time > 0
023 @ $wait.time = wait $wait.time ms
024 end
Cheers.
Oh and to answer the last two posts, loading / saving is NOT one of the tihings that will trigger an interrupt in waits. It has more to do with other commands being executed on an object, which really is only done if the player selects them or some such.
"Nature's first green is gold" . . . stay golden.
-
- Posts: 126
- Joined: Sat, 4. Mar 06, 07:51
Just as an aside regarding the ore belt lag euclid had, that sounds more like the game building up a large amount of resources in the cache during play, which degrades performance over time, and then starting fresh with a clean cache and plenty of room to throw resources about. I've experienced it loads of times in loads of games, when performance got choppy when previously it had been smooth, quitting out and reloading the game usually cleared it up.
This thread's a fascinating read, I'm planning on trying to make some scripts in the future and it's good knowing the stuff that's been discussed here.
This thread's a fascinating read, I'm planning on trying to make some scripts in the future and it's good knowing the stuff that's been discussed here.