• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Extreme Optimization : use only Conditions ?

Status
Not open for further replies.
Level 12
Joined
Jan 30, 2020
Messages
875
Hi again everyone, hope you are all fine.

I am still working on my TD, and as I have fixed the last bugs, removed my weather effects that refused to work (was just a fancy feature anyways), I started working on optimizing my map performance.

Don't get me wrong, I am overall quite pleased with how far I managed to improve the performance so far, but this is a mazing-like Tower Defense, and as you well know, it can become really demanding after a while.

I think I tracked and fixed 99% of potential leaks, there are probably a very few left that are difficult to identify, and also the typical "unfixable leaks".

This said the game performance does not seem to degrade much, except probably with the last level where targets take quite a while to be killed and the number of towers can become consistent.
I have already improved things by slowing towers attacks by a factor of 2, that was compensated with doubling their damage, and increased their range a bit as slow attacks have a much higher chance not to hit targets (yes the targets don't move slower).

I also have a couple of triggers that are quite demanding :
1) The trigger that animates the text printed on the game floor for each player.
- I can't get rid of this feature, this is a total exclusive feature never seen in any other map - ever - so removing it would be sad. The timer between each text scrolling runs every 0.30 second but it only changes models animations so I believe it is OK.
2) The one I am really wondering about is the feature that resizes targets on damage. As the targets are Balls , and these balls looking identical in the same wave, adding some kind of visual pimp actually helps.
I know - especially in a TD map - that even optimized, that event is probably the most demanding in the whole map I still consider removing it for extreme performance - or maybe allowing the map host to disable it with a dialog.

- I don't have any other trigger firing at a high rate.

So I start lacking directions to search for performance gains.

This was until I read old posts on these forums and some others, where people who seemed quite proficient in Jass or at least game mechanics knowledge started discussing the idea of removing trigger ACTIONS and putting all trigger fired code in the CONDITIONS, returning false in the end.

I just wanted to know if this is true.

And if it is (that seems to make sense at first sight), is the performance gain relevant and worth the change ?

Has anyone ever done that in his map and seen a decent performance gain ?

EDIT : in the same optimization process, is it worth pushing my Jass2 even further into vJass and start using structs ? Is there any relevant potential performance gain ?

I really want to make playing the map to become a pleasant experience, so every performance gain will be a bonus for the players.
 
Last edited:
Level 20
Joined
May 16, 2012
Messages
635
If you are familiar with JASS than you will be able to understand this Calling Actions inside Condition.

It's an old post of mine where basically i ask the same thing that you are asking now. There will be a link in the post that will explain the difference between TriggerExecute (AddAction) and TriggerEvaluate (AddContidion) and the performance gains, downsides, etc. Basically, by doing stuff in "Conditions" block you get about 24% more performance from calls but you cannot do stuff like TriggerSleepAction() in your code and stuff like that bacause it will crash the thread. Also, i think you need to have your triggers in jass to be able to do that, since you can not add actions to the conditional block in gui.

Also, on a side note, try to keep control of which triggers need to be enable/disabeld during the game. Talking from personal exp. In my map i've probably did 10000+ lines of code in more than 120 triggers, but performance is solid because i keep track of what needs to be enabled when it needs to be enable, specially those triggers that take action on events like "A Unit is Attacked" or on DDS systems. For Example, if you have a trigger that do some stuff when a specific tower attacks, but there are no towers of that type in the map currently, then why keep this trigger enabled? It might seem like a pointless opttimization, but when they stack up, it might become a problem.
 
Last edited:
Level 12
Joined
Jan 30, 2020
Messages
875
Thank you I will read this carefully.

Don't worry, when I was a mapmaker in 2002-2004, I was already using Jass, and even after 16 years away from Warcraft III, I could not ever consider using GUI ever again :)

UPDATE :

This works really well.

I have not yet tested positive Trigger Sleep Actions in the conditions as I only have 1 currently that I disabled as I am in the process to replace it with a Timer, but so far my 0.00 second Trigger Sleep Actions don't seem to crash the threads.

Thank you again for your link, it was so helpful !!!

EDIT : Forgot to reply to your advice following the link.
Yes I am aware of how bad multiple triggers enabled even when they are not necessary can degrade performance.
I have waves of 10 "attacking" Balls or Flying Balls and "waves" of a single Giant ball or Giant Flying Balls in my map.

What I did is first recycle them (they are all stored hidden in a dedicated rect upon death). Every Ball has its own specific triggers when possible, except for the Entering Region of course. Once the Ball is sent to the storage, its related triggers are disabled, and re-enabled on respawn.

I must admit that when I implemented that change, it made a noticeable performance jump !
 
Last edited:
Level 2
Joined
Mar 8, 2020
Messages
8
A little offtopic - but do you really need so many over-optimizations? I've played many trashy TD and some had LOTS of units and I don't remember any significant lags. I'm interested because - is it really worth to spend time on pushing those 20% perfomance instead of fixing gameplay bugs or implementing new features?
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,180
Verify that there is not some sort of leak causing the performance issues late game. To do pre-setup the "ultimate" tower arrangement for every player on the map and just run the last few waves.

If these perform better than you were observing in actual matches that hit that point then there is some leak going on that degrades performance of some operation as the game progresses. If it performs the same then you have a good setup for verifying optimizations and can work on profiling every aspect.

Just because something is coming from Object Editor data does not necessarily mean it is fast. For example Shadow Strike when set to 0 damage interval can literally freeze WC3 for many seconds. Another example is the piercing damage from the NE ballista/glave thrower which is extremely resource intensive and even within melee games was causing significant performance issues if too many projectiles landed at once. From your "ultimate" tower setup you could try removing, or changing various passives to see if there are performance gains to be had.
 
Level 12
Joined
Jan 30, 2020
Messages
875
Thanks for the incoming extra advice guys, I really do appreciate.

@Pyrogasm : in all fairness, I have actually seen an improvement. Maybe the conditions itself was not the only factor as I had to optimize if checks and remove all TriggerSlaapActions in the end - yes I was wrong, even a 0.00s triggersleep actually crashes the thread. Now everything in the map that requires waits is properly controlled with a local timer that i destroy. and null once expired. I used a single Hashtable to save some sfx and some units, flushed accordingly.
Overall I think after reading many old posts here, I have made sure I did the things properly. It seems to have paid off, although I don't pretend it's perfect yet.

small edit : i don't think there is a need to implement some recycling for the timers, or is there ? I destroy and null them properly everytime they are expired. Is it OK to use local timers or really not advised ?

@Dr Super Good : Thanks for these advices. To be honest, I have reviewed my code over and over again since moving from actions to conditions, and I fail to find any new potential fixable leak. But I think your idea of setting a context of endgame situation to see if it behaves the same or with less lag than a real endgame situation, is really good.
If it shows no significant difference, then I will have to review my whole objects setup as I am well aware of what your are explaining. Will be tough though, and probably requires a bit of reading around to find out what settings I must avoid. I have already fond some around in this forum, but I need to hunt potential avoidable losses of performance if I really want "extreme optimization".
If in the end nothing really makes a difference, i will have to reduce the number of projectiles as I don't have that many intensive passives. I have poison, frost, fire towers, some golems with a terrain-deformation-free version of Slam, a slowing aura, and that's about it.
Now about ultimate towers, some have really long range and maybe cooldowns as low as 0.8s for attacks (and some of these have splash)
All these can be improved with slowing cooldowns and changing damage accordingly, so I have hope.

Overall the map now behaves surprisingly well even in intensive situations whereas before it became a lag fest quite easily. I am happy about this as It will give comfort to the players to enjoy the map. But I feel I can go even further.

So far, I have this trigger I am quite fond of that resizes the balls when they take damage. And even if I worked hard to optimize it as far as I could, I know it can be a real performance hit, so I added a hosting player control to disable / enable that specific resize feature on demand.

Last but not the least, I have failed to understand how preloading works in wc3.
On the version of the map I posted a while back (1.0b), I had pre-placed all towers, all heroes at their max level with all abilities enabled, including dummy units for custom models. They were owned by the computer player owning the Balls, not neutral passive.

It did absolutely nothing : quite often when I click on a newly upgraded tower or hero or a custom spell, I get this 1+2s lag spike.

Is there a simple way to do an efficient preloading ? Or Do I need to load every model file with the Preload() native ?

I have to admit my lack of knowledge in this matter, we didn't use preloading back in my old mapmaking days so this is new territory...

Anyways guys once again, thank you. You have no idea how all this advice helps, and I really am dedicated to my map, and making it really fun to play with the least possible unpleasant issues is my main goal - and I really feel I am getting there, thanks to all the help this forum has provided !
 
Last edited:

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,180
It did absolutely nothing : quite often when I click on a newly upgraded tower or hero or a custom spell, I get this 1+2s lag spike.
One must have had the upgrades reachable for that preload method to work. It also might not work if your system has run out of free memory since the data would have to be paged back in from the page file.

Be aware that Reforged graphics are very memory intensive. The Recommended 8 GB is for dedicated RAM and only for melee and campaign play. Custom maps might need considerably more, especially if other apps are open in the background.
 
Level 12
Joined
Jan 30, 2020
Messages
875
One must have had the upgrades reachable for that preload method to work. It also might not work if your system has run out of free memory since the data would have to be paged back in from the page file.

Be aware that Reforged graphics are very memory intensive. The Recommended 8 GB is for dedicated RAM and only for melee and campaign play. Custom maps might need considerably more, especially if other apps are open in the background.

Yes this is something I tend to forget sometimes. I am quite comfortable with RAM, but I need to take all potential players of my map into account.

I suppose I could try to do some active preloading with issuing a list of orders just after map init and before removing the "preload" units.

I will get inspiration from all your advice and try to make the best out of it. Your experience is precious and very instructive. This place really has many talented people, I am really pleased !
 
Status
Not open for further replies.
Top