Yep, the triggers.xml file can get very very big, in fact, SCUs triggers.xml has a size of almost 80MB. :O
However, when uploading a map and locking it the triggers.xml file will get completly deleted, because its not needed by the game and a missing triggers.xml makes it pretty much impossible to open the map with the normal editor, so you can only edit the galaxy script.
(Just to clarify that the triggers.xml does not increase publish size.)
I wanted to clarify one thing.. compiled code is machine-level code. I don't know for certain if SC2 compiles to machine-level code, but I'm pretty sure it compiles the galaxy script into something closer to machine-level code so I'll call it machine-level for the sake of simplicity..
As far as i know Galaxy is an interpreted language and therefore doesnt get compiled any further. Im not aware of any additional files getting created on code compilation within the maps MPQ, and the performace of the language is so bad that it almost HAS to be interpreted. :)
Quote:
Due to how limited galaxy is and due to its similarity to C and its use of references and strongly-typed variables, I'm pretty certain it's not script. Blizzard used Lua script in WoW for the addon interface, and it was extremely powerful and flexible, so I can only imagine the reason they didn't use that here was for performance.. and to get better performance, that means using a language that's compiled.. not a scripting language. But I digress
I think the main reason why the language is so simple is that it would have been to much work to write a more complex interpreter/compiler. Blizzard could not use a "real" language such as LUA because it would probably have been too powerful (Allowing users to actually damage computers, create files etc) and most features would not work well with a GUI interface, which seems to be their desired way of doing stuff.
The editor was designed to be used by beginners and people who have no programming background, which is why they focused on a very simple scripting language which could do basic tasks.
Quote:
When you're using the trigger editor, everything you do is converted to galaxy script (or code.. or whatever). You can see it by hitting Ctrl+F11. I believe this is the step you're thinking of as being faster using actions vs triggers? This step doesn't affect game performance at all and is virtually immediate within the editor.
Im not 100% certain on this, but i think the compilation from GUI to Galaxy only happens when you save the project, or hit view script. When I said compilation time is longer when using triggers instead of actions i was talking about that particular step.
The actual "compilation" of the .galaxy file is probably just a syntax check.
Quote:
This is the step though that converts all of the galaxy script.. the human-readable code.. into machine-level code. This step could take a little while on really, really large projects and if you get down into it the less galaxy script the faster it would be, but again it's negligible.
As ive said above, i dont think a step like that is actually happening. I think a big chunk of time is spent converting GUI to Galaxy. It doesnt really matter though since triggers will always be slower anyway, because there is more code to be compiled and checked.
Quote:
But to your point, while you could do a custom action to modify them, I feel that defeats the purpose of using the GUI. If you're doing work with the Trigger Editor you're able to rename and move things around and it'll update all references and write function declarations for you.
Good point. I was just saying that its theoretically possible if its really needed though. Its nothing once should do frequently. :D
Quote:
Many of the actions in the Trigger Editor are purely wrappers around native functions that add a little more logic (like getting "default" facing) or simply change the order of the parameters. Every time you use these actions, you're suffering the performance penalty of one more function call. So getting into that discussion is a whole other beast.
Yeah, not only that but some of those wrappers are actually quite horribly coded (You can see the source code of all of them in the libs). I also dislike the fact that in GUI there is no way to see if a function is actually a native or a wrapper function, always have to check for the libNtve prefix in galaxy.
I am not sure if they have any affect what-so-ever on performance; as it is an editor-only dealie.
No, they do not get converted into galaxy at all, its a purely visual GUI thing.
Quote:
Does picking units/players during map init slow the loading down?
Everything you do in script on map init slows the map loading time down by a very small fraction of a second, but i wouldnt know why picking units/players would be worse than anything else.
I pretty much agree with 100% of the stuff you said, just a couple of comments. :)
Quote:
The speed difference here is likely negligible. I don't know how TriggerExecute() works.. it's probably doing a dictionary lookup and calling the associated function, but with proper optimizing, we could be talking nanoseconds. And the difference on a bit-wise operator is even less than that.
Absolutely. As ive said before, it only really makes a different for very frequently executed code, but I actually had quite some amazing results with stuff like unit takes damage.
Quote:
I know this isn't the meaning of your argument, but I want to clarify for anyone else that might read it this way, just because you have less source code doesn't necessarily mean you'll have less or quicker compiled code (and as far as I know, Starcraft 2 does compile the galaxy code).
In this case I disagree that compile speed is not effected. I cant prove it but im almost certain that compiling a trigger takes longer than compilng an action (When saying "compile" im actually talking about converting them from GUI to Galaxy in this case), simply because a lot more code needs to be generated. The actual galaxy compile time should also be faster, because there is less functions overall. Its not really compareable to i+=1 in this case.
Quote:
...even if they do get added to the action list...
Thats a point that I never thought about, but I dont really think its an argument for either side. Triggers also get added to the trigger value list, even though the action list is obviously used more often i never suffered from it since i ALWAYS just use the search bar. Load times also didnt seem to increase significantly.
Quote:
If you're using an event property only once, it's actually quicker to just make the single function call then it would be to store the function result to a variable and pass that variable to a function. As you said, the more you use it, the more performance favors the action.. but it goes the other way too - the less you use it, the more performance favors the initial trigger.
Thats true, but the reality of it is that in 95-99% of all cases you need event responses multiple times, which I would say is why that argument is sort of invalid, even though theoretically correct. Obviously the event handler concept makes most sense for big projects with alot of code.
Quote:
One should never call the same function twice (whether it be a blizz function or one you make yourself) unless you're reasonably certain the outcome will be different.
This is another reason why calling actions is faster. Lets say you go for the good old trigger approach and have 5 triggers with the same event. Even if you write the event properties into local variables in every trigger, they would still get read 5 times, and combining all triggers into one would simply be an absolute nightmare for organization and in reality not really possible. (Even though it would in theory offer best performance).
Quote:
In addition, Actions in the Trigger Editor do not allow you to modify params.
Thats not entirely correct. If the performance benefit is really needed, you can use custom script to modify parameter values. Im not sure why GUI doesnt support it, but its certainly possible.
I would really be interrested in Blizzards reasoning behind not implementing this into GUI. :)
Quote:
Also consider the case where your action is used multiple times but it's only ever called by a single trigger. Say on unit death you want to award bounty. You wire up the events to your trigger, you grab the dead unit and the killing player and send those over to an action to determine the amount of bounty and award it. Now for that, you've created 3 functions (2 for the trigger + 1 for the action) when you really only needed the single trigger (2 functions)... all other things being equal.
The event handler approach doesnt necessary forbid using code directly in the event handlers, but i mostly just do it for 1 liners which are not called from anywhere else, since otherwise the organization is completly messed up.
Quote:
So what I'm saying is that whether or not a trigger or action is "best" depends on the circumstances in which it's being used.
I agree to 100%, but from my experience in reality calling actions always pays of.
Quote:
Also, I'm trying to point out that the war between performance vs organization is exactly that.. almost anytime you do something to better organize your code, you're going to hurt performance. Function calls have overhead associated with them (if you've ever seen assembly code, functions don't actually take params the way we think of it.. you have to first push all the params onto a stack and then the function takes them down off the stack in a consistent order so the more params you have the more expensive your function call is both in terms of memory and performance).
Again absolutly correct, but as said above pasting all code into the same trigger would be insane and is pretty unrealistic. :D
Quote:
Technology is reaching a point where I think performance is becoming less and less of a concern. Processors are getting faster. GPUs are taking on some of the work. That's why I say that until I see benchmarks, most of these concerns are negligible. We're not building nuclear reactors here. :) Everything is a case-by-case.
Right... Still galaxy is about 1000x slower with arithmetical operations than C + +, and even worse with string handling, and we are still programming games were even today C + + dominates for performance reasons, so while its absolutly true that performance in 95% of the time doesnt matter i would still try to use all possible advantages if they dont require too much work or mess up organisation or readability, and the event handlers are a perfect example for that, IMO.
That said, even SCU doesnt use it perfectly and just for very performance intensive pieces of code, alot of the event handlers are very old and still call triggers because im too lazy to convert all of them into actions and the benefit isnt worth it.
So no, im not saying everyone should start converting his code immediately, its just something to consider for future projekts or additions :D
I'll just say, until I can see benchmarking on it, the difference is likely a fraction of a millisecond on something that's only called once so how much does it really matter.
In general this is correct, however there are some scenarios where you can really benefit from using action calls, such as "unit gets damage" or other very frequently called events, especially if the actual code is quite fast, too.
Actons are faster for multiple reasons:
- TriggerExecute() is way slower than just calling a function
- They return void.
- They can check conditions faster than triggers, because the unnecessary negation is missing (Which is used by trigger conditions)
- Event properties just need to be read out once, stored in a variable and then passed by parameter, such as "Triggering Unit". All of those event responses are actually functions which are slower to call than reading variables/parameters, so the more often you need to access event properties the more actions will pull ahead.
Also, as mentioned, the event handler approach produces way way less code, because
- Events dont get added to triggers multiple times
- The action calls itself contain way less galaxy code than triggers, because the trigger initialisation and registration is missing
- Bloated generated code segment such as condition validation or return true/false is not necessary.
Actions, they are faster and produce less code. No reason to use a trigger without events, except a run action needs to be changed at runtime.
My advice: Define "event handlers", meaning ONE trigger per general event, such as unit dies, and from there execute actions (Passing triggering unit as parameter). Fastest and cleanest way of doing things. Also makes it easy to change order of execution and/or to see what exactly happens from that event on.
Yep, the triggers.xml file can get very very big, in fact, SCUs triggers.xml has a size of almost 80MB. :O
However, when uploading a map and locking it the triggers.xml file will get completly deleted, because its not needed by the game and a missing triggers.xml makes it pretty much impossible to open the map with the normal editor, so you can only edit the galaxy script.
(Just to clarify that the triggers.xml does not increase publish size.)
As far as i know Galaxy is an interpreted language and therefore doesnt get compiled any further. Im not aware of any additional files getting created on code compilation within the maps MPQ, and the performace of the language is so bad that it almost HAS to be interpreted. :)
I think the main reason why the language is so simple is that it would have been to much work to write a more complex interpreter/compiler. Blizzard could not use a "real" language such as LUA because it would probably have been too powerful (Allowing users to actually damage computers, create files etc) and most features would not work well with a GUI interface, which seems to be their desired way of doing stuff.
The editor was designed to be used by beginners and people who have no programming background, which is why they focused on a very simple scripting language which could do basic tasks.
Im not 100% certain on this, but i think the compilation from GUI to Galaxy only happens when you save the project, or hit view script. When I said compilation time is longer when using triggers instead of actions i was talking about that particular step.
The actual "compilation" of the .galaxy file is probably just a syntax check.
As ive said above, i dont think a step like that is actually happening. I think a big chunk of time is spent converting GUI to Galaxy. It doesnt really matter though since triggers will always be slower anyway, because there is more code to be compiled and checked.
Good point. I was just saying that its theoretically possible if its really needed though. Its nothing once should do frequently. :D
Yeah, not only that but some of those wrappers are actually quite horribly coded (You can see the source code of all of them in the libs). I also dislike the fact that in GUI there is no way to see if a function is actually a native or a wrapper function, always have to check for the libNtve prefix in galaxy.
No, they do not get converted into galaxy at all, its a purely visual GUI thing.
Everything you do in script on map init slows the map loading time down by a very small fraction of a second, but i wouldnt know why picking units/players would be worse than anything else.
I pretty much agree with 100% of the stuff you said, just a couple of comments. :)
Absolutely. As ive said before, it only really makes a different for very frequently executed code, but I actually had quite some amazing results with stuff like unit takes damage.
In this case I disagree that compile speed is not effected. I cant prove it but im almost certain that compiling a trigger takes longer than compilng an action (When saying "compile" im actually talking about converting them from GUI to Galaxy in this case), simply because a lot more code needs to be generated. The actual galaxy compile time should also be faster, because there is less functions overall. Its not really compareable to i+=1 in this case.
Thats a point that I never thought about, but I dont really think its an argument for either side. Triggers also get added to the trigger value list, even though the action list is obviously used more often i never suffered from it since i ALWAYS just use the search bar. Load times also didnt seem to increase significantly.
Thats true, but the reality of it is that in 95-99% of all cases you need event responses multiple times, which I would say is why that argument is sort of invalid, even though theoretically correct. Obviously the event handler concept makes most sense for big projects with alot of code.
This is another reason why calling actions is faster. Lets say you go for the good old trigger approach and have 5 triggers with the same event. Even if you write the event properties into local variables in every trigger, they would still get read 5 times, and combining all triggers into one would simply be an absolute nightmare for organization and in reality not really possible. (Even though it would in theory offer best performance).
Thats not entirely correct. If the performance benefit is really needed, you can use custom script to modify parameter values. Im not sure why GUI doesnt support it, but its certainly possible.
I would really be interrested in Blizzards reasoning behind not implementing this into GUI. :)
The event handler approach doesnt necessary forbid using code directly in the event handlers, but i mostly just do it for 1 liners which are not called from anywhere else, since otherwise the organization is completly messed up.
I agree to 100%, but from my experience in reality calling actions always pays of.
Again absolutly correct, but as said above pasting all code into the same trigger would be insane and is pretty unrealistic. :D
Right... Still galaxy is about 1000x slower with arithmetical operations than C + +, and even worse with string handling, and we are still programming games were even today C + + dominates for performance reasons, so while its absolutly true that performance in 95% of the time doesnt matter i would still try to use all possible advantages if they dont require too much work or mess up organisation or readability, and the event handlers are a perfect example for that, IMO.
That said, even SCU doesnt use it perfectly and just for very performance intensive pieces of code, alot of the event handlers are very old and still call triggers because im too lazy to convert all of them into actions and the benefit isnt worth it.
So no, im not saying everyone should start converting his code immediately, its just something to consider for future projekts or additions :D
In general this is correct, however there are some scenarios where you can really benefit from using action calls, such as "unit gets damage" or other very frequently called events, especially if the actual code is quite fast, too.
Actons are faster for multiple reasons:
- TriggerExecute() is way slower than just calling a function
- They return void.
- They can check conditions faster than triggers, because the unnecessary negation is missing (Which is used by trigger conditions)
- Event properties just need to be read out once, stored in a variable and then passed by parameter, such as "Triggering Unit". All of those event responses are actually functions which are slower to call than reading variables/parameters, so the more often you need to access event properties the more actions will pull ahead.
Also, as mentioned, the event handler approach produces way way less code, because
- Events dont get added to triggers multiple times
- The action calls itself contain way less galaxy code than triggers, because the trigger initialisation and registration is missing
- Bloated generated code segment such as condition validation or return true/false is not necessary.
Actions, they are faster and produce less code. No reason to use a trigger without events, except a run action needs to be changed at runtime.
My advice: Define "event handlers", meaning ONE trigger per general event, such as unit dies, and from there execute actions (Passing triggering unit as parameter). Fastest and cleanest way of doing things. Also makes it easy to change order of execution and/or to see what exactly happens from that event on.