i have quite a bit of triggers in my map, but I didn't think the limit was near. Whenever I try testing the map now, an error occurs immediately, saying too many threads. It continues with shutting off all triggers. So I have a few questions. First, is this a space problem? Second, if it is a space problem what solutions are there other than deleting triggers? Thanks!
A "thread" is sort of like a "queue" of actions that can be executed simultaneously to other threads. I've never had anything like this happen to me (for threads, that is) and I've had some fairly intensive maps. But this is not a space problem- this is related to the number of threads running inside the map at once- in other words, you have too many triggers or actions running at the same time.
I have a feeling this might be related to an excessive use of action definitions that execute in thier own threads- are you perhaps doing anything like that? See if you're calling a large amount of threaded action definitions from a loop- this process is sometimes called multi-threading, and though it's quite powerful, it can get messed up and this will happen.
If not....then how many triggers are we talking? I can't image you could possibly ever need to have THAT many. A screenshot of your overview manager might be helpful, as well.
In addition to what Zelda said, use the debugger to find out which trigger/action is causing the thread problem, and screenshot it (And triggers that use it if its an action definition)
Alright. I found the problem. I had alot of periodic events, so I lengthened the times. But for future reference, if I want the game to fire the trigger as soon as the conditions are met, what event do I do? In other words, for some of my triggers, I used periodic events just as fillers since there was no event to match up to the specific thing that I wanted. So, is there any what I call place holder event types? It's not much of a problem, but it gets in the way sometimes.
Thanks!
Oh, yeah, that's a problem. There is no "do this as soon as a condition is met" event. The solution is most definitely not to use a ton of periodic events, as you now realize :P
That's part of the puzzle of development- how can you best optimize all of your triggers. There's no one-shot solution to that, unfortunately. You need to take it on a case-by-case basis, and figure out what would work best for your specific map/trigger.
One trick is to run your trigger whenever the thing being checked by the condition is changed. So if I'm checking a certain variable, I'll call the trigger in the same place I change that variable.
Rollback Post to RevisionRollBack
Feel free to Send me a PM if you have any questions/concerns!
If it's possible in Gui, use a while loop with a wait. It's much better than a periodic event firing every x seconds. The way events are handled is very process intensive
First hand encounter with a periodic event causing severe lag in one of my projects. After I switched it to a while loop, the lag magically disappeared. It's only apparent when testing with the debugger on, as it shows your process. With a periodic event that uses the smallest possible time step (0.0625s), the debugger screen gets flooded with events firing, and within a minute SC2 complains that I need to lower my graphics setting. With the while loop approach, this doesn't happen.
With the debugger off, the lag isn't obvious, but background process wise, it is taking up more of the process because of the event handler firing rapidly. Map attached as proof. Just disable the 'PeriodTest' and enable 'WhileTest' to do the comparison. Also, make sure to turn on the debugger to see the difference.
With a periodic event that uses the smallest possible time step (0.0625s), the debugger screen gets flooded with events firing, and within a minute SC2 complains that I need to lower my graphics setting. With the while loop approach, this doesn't happen.
Its obvious that there is a difference when having the debugger on (AND not turning off event-fire messages in the debugger.)
So whats your point?
Quote:
With the debugger off, the lag isn't obvious, but background process wise, it is taking up more of the process because of the event handler firing rapidly.
So how do you get to that conclusion?
Quote:
Also, make sure to turn on the debugger to see the difference.
Turn the event-fire messages off and see what happens.
Alright. I found the problem. I had alot of periodic events, so I lengthened the times. But for future reference, if I want the game to fire the trigger as soon as the conditions are met, what event do I do? In other words, for some of my triggers, I used periodic events just as fillers since there was no event to match up to the specific thing that I wanted. So, is there any what I call place holder event types? It's not much of a problem, but it gets in the way sometimes. Thanks!
say your Condition is something like reaching 100 kills....
at the end of your Kill Detection trigger you would fire off another trigger or action definition that checks to see if the conditions are met.
you can fire this condition check off after anything that might be a condition being met....
this way you dont have to check to see if conditions are met every 0.0 seconds but rather immediately after a condition is met.
Rollback Post to RevisionRollBack
Skype
KageNinpo = SN
My Libraries
DialogLeaderboard & TeamSort
My Projects
SPACEWAR Tribute
Infinite TD
My point, is that I believe events do not perform as well as a while loop with waits on the processor and memory (RAM) level. Each event that fires, opens a new thread (Every trigger is run on a separate thread). The more threads we have running in parallel, the more your processor core is going to distribute its processing power. Evidence of this happening is the OP's post, in which a claim was made whereby he had a lot of periodic events.
So how do you get to that conclusion?
Based on my understanding of how Triggers work on the process and memory (RAM) level. 1 Event firing = 1 Trigger queued into your RAM, which the processor will in turn process in it's own thread. Lets say for example, we have 20 periodic events with the smallest time step possible. That's 20 / 0.0625 = 320 threads being created in the span of 1 second.
So what happens when each of these threads takes longer than 0.0625 seconds to execute? The processors load gets constantly divided. As this occurs, each thread begins to take longer and longer to run (Because of the distributed load). This, in conclusion, is the root cause of the lag experienced from the user's perspective.
This does not happen with the alternative, a trigger with a while loop, because it only queues a single thread into the processor. The less threads there are, the less the processors load is divided, thus resulting in better performance.
Hope that made sense.
PS: One might argue that a workaround to this is to simply not have such a short time step between periodic events. My counter-argument:
Sure, but it also means the frequency that the trigger can run is restricted.
I believe it is not a good coding practice in the long run, especially as a project continues to grow in script/memory usage size
My point, is that I believe events do not perform as well as a while loop with waits. Each event that fires, opens a new thread (Every trigger is run on a separate thread). The more threads you have running in parallel, the more your processor core is going to distribute its processing power. Evidence of this happening is the OP's post, in which a claim was made whereby he had a lot of periodic events.
While its true that each trigger will open a new thread, this doesnt mean that the threads are building up. Usually the execution of a trigger takes ALOT less time than 0.0625 seconds, what means there is not even 1 thread active at the whole time when using a periodic event.
Also think about this: When using a while loop, you will have a permanent thread running as long until the loop breaks.
In addition, if the execution of the trigger takes longer than 0.0625 seconds a while loop wouldnt even be able to execute the code all 0.0625 seconds since the loop execution time is dependent on the code within it.
Quote:
Based on my understanding
....
..
..
All this stuff is just theory. You dont know how threads in Starcraft exactly work or how long it takes to create/destroy them/how efficient they are.
The wait action used in a while loop is most likely also creating a thread by itself.
As a conclusion, I think we could discuss about efficience of loops etc for hours, but in fact we just cant know how exactly all this stuff internally works and how its implemented.
Most likely id say there is no difference between both methods, until someone gives me a clear test that proves the opposite.
If you want to optimize your code, you shouldnt really care about stuff like this but much more likely take a look at your algorythms and code structure. Its a common mistake to break down performance to stuff like loops vs timer etc, since most likely it wont change anything at all (its like a hair cut to lose weight).
I rest my case for now, It's 4 am, need sleep. Thanks for the discussion, you've made some excellent points that I do not currently have a counter-argument to.
Most likely id say there is no difference between both methods, until someone gives me a clear test that proves the opposite.
I'll post a response to this if I'm able to find some conclusive evidence.
Thought I'd share what looks to be an interesting read though: Trigger Mechanics
Although the author states its relatively theory, it's very detailed explanation, and the guy seems to know his stuff. I plan to have a detailed read myself when I've the time, as it might resolve some of the doubts we've had during our debate.
Edit: Section 7 in the link explains very clearly what I was trying to explain earlier. I was slightly mistaken on the way triggers are handled though. There is actually a scheduler and a trigger queue which controls trigger execution. When the queue gets to long, that's when we start to experience lag
i have quite a bit of triggers in my map, but I didn't think the limit was near. Whenever I try testing the map now, an error occurs immediately, saying too many threads. It continues with shutting off all triggers. So I have a few questions. First, is this a space problem? Second, if it is a space problem what solutions are there other than deleting triggers? Thanks!
@littlefury916: Go
A "thread" is sort of like a "queue" of actions that can be executed simultaneously to other threads. I've never had anything like this happen to me (for threads, that is) and I've had some fairly intensive maps. But this is not a space problem- this is related to the number of threads running inside the map at once- in other words, you have too many triggers or actions running at the same time.
I have a feeling this might be related to an excessive use of action definitions that execute in thier own threads- are you perhaps doing anything like that? See if you're calling a large amount of threaded action definitions from a loop- this process is sometimes called multi-threading, and though it's quite powerful, it can get messed up and this will happen.
If not....then how many triggers are we talking? I can't image you could possibly ever need to have THAT many. A screenshot of your overview manager might be helpful, as well.
In addition to what Zelda said, use the debugger to find out which trigger/action is causing the thread problem, and screenshot it (And triggers that use it if its an action definition)
Alright. I found the problem. I had alot of periodic events, so I lengthened the times. But for future reference, if I want the game to fire the trigger as soon as the conditions are met, what event do I do? In other words, for some of my triggers, I used periodic events just as fillers since there was no event to match up to the specific thing that I wanted. So, is there any what I call place holder event types? It's not much of a problem, but it gets in the way sometimes. Thanks!
@littlefury916: Go
Oh, yeah, that's a problem. There is no "do this as soon as a condition is met" event. The solution is most definitely not to use a ton of periodic events, as you now realize :P
That's part of the puzzle of development- how can you best optimize all of your triggers. There's no one-shot solution to that, unfortunately. You need to take it on a case-by-case basis, and figure out what would work best for your specific map/trigger.
One trick is to run your trigger whenever the thing being checked by the condition is changed. So if I'm checking a certain variable, I'll call the trigger in the same place I change that variable.
If it's possible in Gui, use a while loop with a wait. It's much better than a periodic event firing every x seconds. The way events are handled is very process intensive
@FuzzYD:
Source?
First hand encounter with a periodic event causing severe lag in one of my projects. After I switched it to a while loop, the lag magically disappeared. It's only apparent when testing with the debugger on, as it shows your process. With a periodic event that uses the smallest possible time step (0.0625s), the debugger screen gets flooded with events firing, and within a minute SC2 complains that I need to lower my graphics setting. With the while loop approach, this doesn't happen.
With the debugger off, the lag isn't obvious, but background process wise, it is taking up more of the process because of the event handler firing rapidly. Map attached as proof. Just disable the 'PeriodTest' and enable 'WhileTest' to do the comparison. Also, make sure to turn on the debugger to see the difference.
Its obvious that there is a difference when having the debugger on (AND not turning off event-fire messages in the debugger.)
So whats your point?
So how do you get to that conclusion?
Turn the event-fire messages off and see what happens.
say your Condition is something like reaching 100 kills....
at the end of your Kill Detection trigger you would fire off another trigger or action definition that checks to see if the conditions are met.
you can fire this condition check off after anything that might be a condition being met....
this way you dont have to check to see if conditions are met every 0.0 seconds but rather immediately after a condition is met.
@Mille25: Go
So whats your point?
My point, is that I believe events do not perform as well as a while loop with waits on the processor and memory (RAM) level. Each event that fires, opens a new thread (Every trigger is run on a separate thread). The more threads we have running in parallel, the more your processor core is going to distribute its processing power. Evidence of this happening is the OP's post, in which a claim was made whereby he had a lot of periodic events.
So how do you get to that conclusion?
Based on my understanding of how Triggers work on the process and memory (RAM) level. 1 Event firing = 1 Trigger queued into your RAM, which the processor will in turn process in it's own thread. Lets say for example, we have 20 periodic events with the smallest time step possible. That's 20 / 0.0625 = 320 threads being created in the span of 1 second.
So what happens when each of these threads takes longer than 0.0625 seconds to execute? The processors load gets constantly divided. As this occurs, each thread begins to take longer and longer to run (Because of the distributed load). This, in conclusion, is the root cause of the lag experienced from the user's perspective.
This does not happen with the alternative, a trigger with a while loop, because it only queues a single thread into the processor. The less threads there are, the less the processors load is divided, thus resulting in better performance.
Hope that made sense.
PS: One might argue that a workaround to this is to simply not have such a short time step between periodic events. My counter-argument:
While its true that each trigger will open a new thread, this doesnt mean that the threads are building up. Usually the execution of a trigger takes ALOT less time than 0.0625 seconds, what means there is not even 1 thread active at the whole time when using a periodic event.
Also think about this: When using a while loop, you will have a permanent thread running as long until the loop breaks.
In addition, if the execution of the trigger takes longer than 0.0625 seconds a while loop wouldnt even be able to execute the code all 0.0625 seconds since the loop execution time is dependent on the code within it.
All this stuff is just theory. You dont know how threads in Starcraft exactly work or how long it takes to create/destroy them/how efficient they are.
The wait action used in a while loop is most likely also creating a thread by itself.
As a conclusion, I think we could discuss about efficience of loops etc for hours, but in fact we just cant know how exactly all this stuff internally works and how its implemented.
Most likely id say there is no difference between both methods, until someone gives me a clear test that proves the opposite.
If you want to optimize your code, you shouldnt really care about stuff like this but much more likely take a look at your algorythms and code structure. Its a common mistake to break down performance to stuff like loops vs timer etc, since most likely it wont change anything at all (its like a hair cut to lose weight).
@Mille25: Go
I rest my case for now, It's 4 am, need sleep. Thanks for the discussion, you've made some excellent points that I do not currently have a counter-argument to.
Most likely id say there is no difference between both methods, until someone gives me a clear test that proves the opposite.
I'll post a response to this if I'm able to find some conclusive evidence.
Thought I'd share what looks to be an interesting read though: Trigger Mechanics
Although the author states its relatively theory, it's very detailed explanation, and the guy seems to know his stuff. I plan to have a detailed read myself when I've the time, as it might resolve some of the doubts we've had during our debate.
Edit: Section 7 in the link explains very clearly what I was trying to explain earlier. I was slightly mistaken on the way triggers are handled though. There is actually a scheduler and a trigger queue which controls trigger execution. When the queue gets to long, that's when we start to experience lag