[Solved] lag on "Exit program"

Level 21
Joined
Mar 29, 2020
Messages
1,235
hey there,

The map I'm working on recently developed a strange and unpleasant habit - whenever I exit the map it lags for 10 - 20 seconds before exiting.

I can't figure out what caused it, but assume this is a bad sign and shouldn't be ignored. I thought it was because of new triggers I had created, but even when they are deactivated this happens.

has anyone encountered this or know why it's happening? thanks.
 
Level 6
Joined
Mar 7, 2011
Messages
124
i've never heard of that happening at all

it'd be very unusual if that issue was because of your specific map. have you already checked that from a few different angles? what happens when you try first closing your custom map (not the editor) before then exiting the editor? what happens when you exit the editor from another map, such as a basic melee map?

id be tempted to just try restarting / reinstalling and see if that fixes it
 

Uncle

Warcraft Moderator
Level 47
Joined
Aug 10, 2018
Messages
4,615
Maybe some trigger revolving around the "Player leaves the game" event?
 
Level 6
Joined
Mar 7, 2011
Messages
124
oh sorry, i thought you meant when exiting from the world editor. i think zwie's idea might still fit. it also takes a long time to exit from the score screen?

you might try disabling all your triggers and seeing how that goes. it should be a lot easier to fix this issue when you know the game exits properly, and then you add things back until you can clearly see the long exit times again
 

Dr Super Good

Spell Reviewer
Level 62
Joined
Jan 18, 2005
Messages
27,083
I had this as well! Did you try if other maps show this behaviour as well? For me all maps had it. What solved it was simply to restart the pc...
This would point towards the computer being low on free memory. Possibly due to a bugged process such as a game that was long since crashed or closed but the process was not terminated.
 
Level 11
Joined
May 16, 2020
Messages
657
This would point towards the computer being low on free memory. Possibly due to a bugged process such as a game that was long since crashed or closed but the process was not terminated.

The memory was actually looking fine if I remember correctly. But I haven’t restarted the pc in a week back then and similar to the original poster all my maps started to be very slow when clicking “exit” from one “test map” to the next.

I don’t think that leaks were the cause, but as you said just some “bugged processes” for whatever reason. Everything thankfully went back to normal after restarting.
 
Level 21
Joined
Mar 29, 2020
Messages
1,235
no, for me it only happened with this one map, so I guess I'll start rechecking all of my recent triggers...

thanks


Edit:- can't find anything. I have barely any init triggers and those are very simple and don't have much that could leak, none of my looping triggers are activated, I turned off everything new - this still happens.

the first time it happened I was testing out a new loop before de-leaking it. is it possible it somehow leaked then and the map never successfully got rid of the leaks? sounds silly... or is that how maps get bugged?
 
Last edited:

Dr Super Good

Spell Reviewer
Level 62
Joined
Jan 18, 2005
Messages
27,083
the first time it happened I was testing out a new loop before de-leaking it. is it possible it somehow leaked then and the map never successfully got rid of the leaks? sounds silly... or is that how maps get bugged?
Leaks only happen in game and have little to do with editor performance. The editor might have its own memory leak bugs, but these have nothing to do with the maps it outputs and will not add to map complexity.
 
Level 21
Joined
Mar 29, 2020
Messages
1,235
ok, this has gotten pretty ridiculous now.

I made double sure - and other maps are closing just fine for me. I created a brand new map, and copied over all of the triggers - and voila, the problem is happening there too. so I turned off every single trigger in the map one by one, and the problem is still there.

can triggers that are off (disabled) still cause leaks? there is literally nothing else on the map but all of my deactivated triggers (and a footman and a paladin), and it is lagging 20 seconds when I exit map from a test run.

:vw_death::vw_death::vw_death::vw_death::vw_death:
 
Level 21
Joined
Mar 29, 2020
Messages
1,235
I frickin found it.

it was a variable - a unit group array that I had set to the size of 32768 as per @Uncle 's intructions. Anyone know why this spazzing out my map and what I am doing wrong? If you want to see it in my map it is in the folder named "leak removal" and the variable is called carriedDummyGroup.
 
Level 19
Joined
Aug 13, 2013
Messages
1,679
I can't remember the mystery behind it anymore, (it's been a decade since this was talked about) but you should know that indexes near to JASS_MAX_ARRAY_SIZE have notoriously known to cause some strange bugs within it and this might be related to your case.

Besides, the real question here is why initialize the size of an array to that value anyway?
Most people leave that field to 1 unless you're reading an uninitialized index value which may cause problem just like with uninitialized locals.
 
Level 19
Joined
Aug 13, 2013
Messages
1,679
um... I don't know why. my ability wasn't working, and @Uncle suggested to do that so I did. Afterwards the ability worked...
So the answer to that is simply this;
Most people leave that field to 1 unless you're reading an uninitialized index value which may cause problem just like with uninitialized locals.
The reason why It wouldn't work because you might just reading or using it without initializing the value first which may lead to null value.
Initializing lots of empty indexes unused is not that logical, and this might be the reason why there's a strange "delay" exiting your map.

EDIT:

This "delay" might be explicitly pointed out by @Dr Super Good already:
Usually this is caused by leaks. When the client leaves a game Warcraft III must clean up all the leaked objects. The complexity of doing this might not be linear which is why the delay/freeze when leaving a game seems to become exponentially worse.
In this case, lots of groups are created which are meant to be destroyed once the game exits.
(Not to mention you aren't destroying these 30000+ groups created at the same time anyway)
 
Last edited:
Level 19
Joined
Aug 13, 2013
Messages
1,679
I actually don't get what setting the initial size of an array does, since no other arrays need this...
It's just for safety. Make that size to 5 and it will create 5 variable indexed with the initial value you specified.
So what solution would you suggest?
Depending on how you're using the variable, kindly post the scripts that's using it so we could settle the things properly.
 
Level 21
Joined
Mar 29, 2020
Messages
1,235
I plan on fixing it up a little, but this is the basic use of the unit group array. (I am using bribe's unit indexer and damage engine)

  • Carried init
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Unknown (A02C)
    • Actions
      • Set ID = (Custom value of (Triggering unit))
      • Set TempPoint1 = (Position of (Triggering unit))
      • Unit Group - Remove all units from Temp_Group
      • Unit Group - Pick every unit in (Units within 500.00 of TempPoint1) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) is A structure) Equal to False
              • ((Picked unit) is An Ancient) Equal to False
              • ((Picked unit) is Mechanical) Equal to False
              • ((Picked unit) is Magic Immune) Equal to False
              • ((Picked unit) is an illusion) Equal to False
              • ((Picked unit) is dead) Equal to False
              • (Supply used by (Picked unit)) Greater than 0
              • ((Picked unit) belongs to an ally of (Triggering player)) Equal to True
            • Then - Actions
              • Unit Group - Add (Picked unit) to Temp_Group
            • Else - Actions
      • Set TempInteger = (Number of units in Temp_Group)
      • Set CarriedFraction[ID] = (1.00 / (Real(TempInteger)))
      • Unit Group - Pick every unit in Temp_Group and do (Actions)
        • Loop - Actions
          • Set TempPoint = (Position of (Picked unit))
          • Unit - Create 1 for (Triggering player) at TempPoint facing Default building facing degrees
          • Set CV = (Custom value of (Last created unit))
          • Unit Group - Add (Last created unit) to CarriedDummyGroup[ID]
          • Set CarriedTarget[CV] = (Picked unit)
          • Lightning - Create a Magic Leash lightning effect from source TempPoint1 to target TempPoint
          • Lightning - Change color of (Last created lightning effect) to (1.00 0.00 1.00) with 0.60 alpha
          • Set CarriedLightning[CV] = (Last created lightning effect)
          • Custom script: call RemoveLocation (udg_TempPoint)
      • Unit Group - Add (Triggering unit) to CarriedCasterGroup
      • Custom script: call RemoveLocation (udg_TempPoint1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Carried periodic <gen> is on) Equal to False
        • Then - Actions
          • Trigger - Turn on Carried periodic <gen>
        • Else - Actions
  • Carried init
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Unknown (A02C)
    • Actions
      • Set ID = (Custom value of (Triggering unit))
      • Set TempPoint1 = (Position of (Triggering unit))
      • Unit Group - Remove all units from Temp_Group
      • Unit Group - Pick every unit in (Units within 500.00 of TempPoint1) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) is A structure) Equal to False
              • ((Picked unit) is An Ancient) Equal to False
              • ((Picked unit) is Mechanical) Equal to False
              • ((Picked unit) is Magic Immune) Equal to False
              • ((Picked unit) is an illusion) Equal to False
              • ((Picked unit) is dead) Equal to False
              • (Supply used by (Picked unit)) Greater than 0
              • ((Picked unit) belongs to an ally of (Triggering player)) Equal to True
            • Then - Actions
              • Unit Group - Add (Picked unit) to Temp_Group
            • Else - Actions
      • Set TempInteger = (Number of units in Temp_Group)
      • Set CarriedFraction[ID] = (1.00 / (Real(TempInteger)))
      • Unit Group - Pick every unit in Temp_Group and do (Actions)
        • Loop - Actions
          • Set TempPoint = (Position of (Picked unit))
          • Unit - Create 1 for (Triggering player) at TempPoint facing Default building facing degrees
          • Set CV = (Custom value of (Last created unit))
          • Unit Group - Add (Last created unit) to CarriedDummyGroup[ID]
          • Set CarriedTarget[CV] = (Picked unit)
          • Lightning - Create a Magic Leash lightning effect from source TempPoint1 to target TempPoint
          • Lightning - Change color of (Last created lightning effect) to (1.00 0.00 1.00) with 0.60 alpha
          • Set CarriedLightning[CV] = (Last created lightning effect)
          • Custom script: call RemoveLocation (udg_TempPoint)
      • Unit Group - Add (Triggering unit) to CarriedCasterGroup
      • Custom script: call RemoveLocation (udg_TempPoint1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Carried periodic <gen> is on) Equal to False
        • Then - Actions
          • Trigger - Turn on Carried periodic <gen>
        • Else - Actions
  • Carried damage current
    • Events
      • Game - DamageModifierEvent becomes Equal to 1.00
    • Conditions
      • (DamageEventTarget is in CarriedCasterGroup) Equal to True
    • Actions
      • Set TempUnit = DamageEventSource
      • Set TempReal = DamageEventAmount
      • Set ID = (Custom value of DamageEventTarget)
      • Set real = (CarriedFraction[ID] x TempReal)
      • Set TempInteger = (Number of units in CarriedDummyGroup[ID])
      • Set DamageEventAmount = (DamageEventAmount - (real x (Real(TempInteger))))
      • Unit Group - Pick every unit in CarriedDummyGroup[ID] and do (Actions)
        • Loop - Actions
          • Set CV = (Custom value of (Picked unit))
          • Set NextDamageType = DamageEventDamageT
          • Unit - Cause TempUnit to damage CarriedTarget[CV], dealing real damage of attack type CONVERTED_ATTACK_TYPE[DamageEventAttackT] and damage type CONVERTED_DAMAGE_TYPE[DamageEventDamageT]
 
Level 19
Joined
Aug 13, 2013
Messages
1,679
I don't see any udg_CarriedDummyGroup[udg_ID] initialized in the scripts. Where's the periodic?
I'm only seeing you're using the unit group array without creating that group indexed anywhere.
And that's the reason why you're spell/ability is failing as you're just pointing to a null unit group.

This forces you to use an initialized indexes which are redundant if all were not used and not very practical.
Just use custom scripts for this: indexing the unit group which created by CreateGroup() and destroyed by DestroyGroup() functions after use.
 

Dr Super Good

Spell Reviewer
Level 62
Joined
Jan 18, 2005
Messages
27,083
can triggers that are off (disabled) still cause leaks?
No they cannot as they generate no script that Warcraft III executes during gameplay.
If you're not using reforged editor to save the map, kindly send it here so I can take a look of it. (even privately)
So we could identify the problem quickly than just guessing it.
We have to support the latest version of Warcraft III here. I suggest you dual install if you plan to help out.
it was a variable - a unit group array that I had set to the size of 32768 as per @Uncle 's intructions. Anyone know why this spazzing out my map and what I am doing wrong? If you want to see it in my map it is in the folder named "leak removal" and the variable is called carriedDummyGroup.
One could consider this a leak of ~32,700 odd objects, which can cause increased exit times. Usually this happens with more objects, but maybe because they are referenced they just slow down the speed all other leaks (or objects?) are cleaned.
lol, thanks @JAKEZINC . any idea why that is doing that? isn't that (setting to max size) what I have to do with a unit group array to get it to function?
You just need to create new groups as you need them. All that size variable does is initialize the specified number of indices with the specified default value, an empty group. One can keep the indices uninitialized and then use JASS/Lua script to manually initialize them as required.
 
Last edited:

Uncle

Warcraft Moderator
Level 47
Joined
Aug 10, 2018
Messages
4,615
@Ender Wiggins
I had never experienced the slow down from creating large array sizes like that, but yeah, apologies if this caused problems.

I'm pretty sure this is all you need to do to initialize like others have recommended:
  • Custom script: set udg_carriedDummyGroup[udg_CV] = CreateGroup()
^ That will create the Unit Group using CV as the Index

Then destroy it down the line when you no longer need it:
  • Custom script: call DestroyGroup(udg_carriedDummyGroup[udg_CV])
 
Level 21
Joined
Mar 29, 2020
Messages
1,235
I don't see any udg_CarriedDummyGroup[udg_ID] initialized in the scripts. Where's the periodic?
I'm only seeing you're using the unit group array without creating that group indexed anywhere.
And that's the reason why you're spell/ability is failing as you're just pointing to a null unit group.

This forces you to use an initialized indexes which are redundant if all were not used and not very practical.
Just use custom scripts for this: indexing the unit group which created by CreateGroup() and destroyed by DestroyGroup() functions after use.

oh, sorry. looks like I posted the initialization trigger twice instead of adding the periodic trigger.

  • Carried periodic
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in CarriedCasterGroup and do (Actions)
        • Loop - Actions
          • Set ID = (Custom value of (Picked unit))
          • Set TempUnit = (Picked unit)
          • Set CarriedCounter[ID] = (CarriedCounter[ID] + 0.05)
          • Set TempPoint = (Position of (Picked unit))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • (CarriedDummyGroup[ID] is empty) Equal to True
                  • (TempUnit is dead) Equal to True
                  • (TempUnit is being transported) Equal to True
            • Then - Actions
              • Set CarriedCounter[ID] = 0.00
              • Unit Group - Remove TempUnit from CarriedCasterGroup
            • Else - Actions
          • Unit Group - Pick every unit in CarriedDummyGroup[ID] and do (Actions)
            • Loop - Actions
              • Set CV = (Custom value of (Picked unit))
              • Set TempPoint1 = (Position of CarriedTarget[CV])
              • Lightning - Move CarriedLightning[CV] to source TempPoint and target TempPoint1
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Or - Any (Conditions) are true
                    • Conditions
                      • CarriedCounter[ID] Greater than or equal to 300.00
                      • (CarriedTarget[CV] is dead) Equal to True
                      • (CarriedTarget[CV] is being transported) Equal to True
                      • (Distance between TempPoint and TempPoint1) Greater than or equal to 3000.00
                • Then - Actions
                  • Unit Group - Remove (Picked unit) from CarriedDummyGroup[ID]
                  • Unit - Remove (Picked unit) from the game
                  • Lightning - Destroy CarriedLightning[CV]
                • Else - Actions
              • Custom script: call RemoveLocation (udg_TempPoint1)
          • Custom script: call RemoveLocation (udg_TempPoint)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (CarriedCasterGroup is empty) Equal to True
        • Then - Actions
          • Trigger - Turn off (This trigger)
          • Game - Display to (All players) the text: loop turned off
        • Else - Actions

We have to support the latest version of Warcraft III here. I suggest you dual install if you plan to help out.
could you explain why? it's not like we're talking about some pirated or bootlegged version. we're talking about legally owned blizzard software that we just didn't update yet bc reforged still has some kinks to work out. why is that a problem?
apologies if this caused problems.
you really have nothing to apologize about, I wasn't blaming you, I was just citing you as my legitimate source for doing that... I have only gratitude towards you. without your help my map would pretty much still be a word document of ideas.

That will create the Unit Group using CV as the Index

and when doing this what do I set the array size to initially?
 

Dr Super Good

Spell Reviewer
Level 62
Joined
Jan 18, 2005
Messages
27,083
could you explain why? it's not like we're talking about some pirated or bootlegged version. we're talking about legally owned blizzard software that we just didn't update yet bc reforged still has some kinks to work out. why is that a problem?
Why should a user be forced to find some old, unsupported and buggy version of Warcraft III to get help? I do not think it is reasonable to only offer help to people with obsolete versions.

If a person is making their map using the latest version of Warcraft III then help should be given for that. If a person is using an older version of Warcraft III they should expect that features only supported by the latest version of Warcraft III might end up being referenced, especially if they do not mention that they are using an older version of Warcraft III.
and when doing this what do I set the array size to initially?
JASS arrays are dynamic arrays and treat all indices as initialized to a default value, up to a Blizzard defined maximum index. In the case of handles this default value is null. As such outside of using a different initial value for the starting portion of the array, the "size" field does nothing and can be left at 1. One can then initialize it with a value, such as via CreateGroup, when the index is used and destroy and null that value when it is no longer in use.

This distinction is important as not all languages use dynamic arrays. For example in StarCraft II with its Galaxy scripting language the size field is required as array indices larger than the array size value throw an exception. This was one of the biggest problems that people moving from Warcraft III to StarCraft II faced as it prevented them from using their staple indexing systems efficiently.
 
Level 21
Joined
Mar 29, 2020
Messages
1,235
when I initialize as specified I get this:

upload_2020-7-13_12-52-8.png
 
Level 18
Joined
Jan 1, 2018
Messages
727
Why should a user be forced to find some old, unsupported and buggy version of Warcraft III to get help? I do not think it is reasonable to only offer help to people with obsolete versions.
And I don't think it's reasonable to be forced to download 30GB of crap just to open some reforged map that someone needs help with :)
nospace.png


when I initialize as specified I get this:
You forget the set keyword.
 

Dr Super Good

Spell Reviewer
Level 62
Joined
Jan 18, 2005
Messages
27,083
when I initialize as specified I get this:
The "set" keyword is required when using JASS.
And I don't think it's reasonable to be forced to download 30GB of crap just to open some reforged map that someone needs help with :)
Given how 30 GB is a small game now. It seems quite reasonable.
 

pyf

pyf

Level 31
Joined
Mar 21, 2016
Messages
2,986
And I don't think it's reasonable to be forced to download 30GB of crap just to open some reforged map that someone needs help with :)
nospace-png.359412
@Drake53: Do you think it is Warcraft 3 v1.32 alone which has clobbered up this HDD? Time for you to maybe hunt for some other crap imho.

Given how 30 GB is a small game now. It seems quite reasonable.
@Dr Super Good: debatable; but not in this thread.
 
Level 18
Joined
Jan 1, 2018
Messages
727
@Drake53: Do you think it is Warcraft 3 v1.32 alone which has clobbered up this HDD? Time for you to maybe hunt for some other crap imho.
I already uninstalled reforged when I took that screenshot, my point was that I wouldn't be able to re-install it even if I wanted to.
 

pyf

pyf

Level 31
Joined
Mar 21, 2016
Messages
2,986
Maybe you need to uninstall/delete/move more stuff?

For the record, when a SSD drive is filled up to a point, its performance starts degrading (unless you are using overprovisioning). Also, when upgrading to a new OS version, modern versions of Windows need extra space for the upgrade to succeed, and also to keep a temporary backup copy of the previous version of the OS. This is what happens with Windows 10 for example.
 
Level 18
Joined
Jan 1, 2018
Messages
727
Maybe you need to uninstall/delete/move more stuff?
Yes I do, but I have a lot of important stuff so it's hard to find things that I can get rid of.

For the record, when a SSD drive is filled up to a point, its performance starts degrading (unless you are using overprovisioning).
Performance already went to shit, often at 100% usage in task manager.

Also, when upgrading to a new OS version, modern versions of Windows need extra space for the upgrade to succeed, and also to keep a temporary backup copy of the previous version of the OS. This is what happens with Windows 10 for example.
I'll never 'upgrade' to an inferior version of a product.
 

Dr Super Good

Spell Reviewer
Level 62
Joined
Jan 18, 2005
Messages
27,083
(unless you are using overprovisioning)
Most reputable drivers will already have some form of over provisioning as that is how they reach their TBW (TeraBytes Written) warrantee. However that is not necessarily enough to prevent the write performance degradation from a full drive.

Only write performance is affected by a full drive. This is because there might be too few empty flash macro blocks to write new data into. As such it will have to make some by compacting existing ones which takes both time and increases write amplification. Read only performance should remain the same since no data will be moved around unless errors are detected by error correcting code, in which case the read operation will turn into a write one as well but that will only happen frequently after the TBW of the drive was reached.

Performance already went to shit, often at 100% usage in task manager.
In that case I suggest using a larger drive, or maybe holding bulk data in a separate drive. 1TB of SATA SSD costs roughly £/$ 100 now and might get cheaper over the next few months by up to 10% due to oversupply.
I'll never 'upgrade' to an inferior version of a product.
Latest updates for Windows 10 are strongly recommended due to security improvements as well as newer API support. They fulfil all meanings of the word "upgrade".
 
Level 18
Joined
Jan 1, 2018
Messages
727
In that case I suggest using a larger drive, or maybe holding bulk data in a separate drive.
I already have a 2TB external HDD, just never have the time to move not-so-important files to it.

Latest updates for Windows 10 are strongly recommended due to security improvements as well as newer API support.
Security improvements are overrated. The biggest security risk is being a naive tech-illiterate. That's not something you can fix with software updates.
 

pyf

pyf

Level 31
Joined
Mar 21, 2016
Messages
2,986
Top