| 01-09-2004, 05:55 AM | #1 |
Okay, I am learning some stuff from the blizzard td, but I have a question. Why do they create a temp point everytime they do a move event and then delete it rather than just using random point in region, which is what the temp point is? If you just order a unit to go to random point in region does it create a mem leak, where as making a temp point doesn't? I am quite confused as it seems to be unnescesary coding. |
| 01-09-2004, 07:41 AM | #2 |
It is precisely to prevent a memory leak. |
| 01-09-2004, 07:56 AM | #3 |
Grabbing a random point in a rect stores the point in memory indefinetly? |
| 01-09-2004, 07:57 AM | #4 |
Okay heres the long and the short of it, if you DONT manually assign a location to a variable and destroy it then it IS leaked. There are no exceptions. THe same is true for many other non-basic types (integers, reals, unit etc), Unit groups, SFX, Floating Text, all must be manually destroyed even it looks like it doesn't. *** WARNING *** There is one case when you must not destroy variables, if you have two variables (be they locations, or unit groups or whatever) and do: Set A = B Then A and B are now the same variable, changing one changes the other, destroying one destroys the other, because they are the same - this is also true if B is an elemant of an array. In fact you should never set one variable to another, if you want to copy a location you can use the GUI actions like A = "Point with Offset(B, 0.0, 0.0)" For unit groups you do something odd like: Clear A Copy all units from Unit group B to Unit Group A Anyway thought I better add that warning because assigning one variable directely to another is bad practise and will almost certainitely lead to seemingly inexplicable bugs which are very uncool. |
| 01-09-2004, 09:40 AM | #5 |
Okay, so why do you have to destroy the variable everytime? if you set temppoint = to random location, what is wrong with leaving it set to that until it is changed? does that still cause mem leak? |
| 01-09-2004, 10:07 AM | #6 |
Okay lets see if I can explain it, a Point or UnitGroup variable in the GUI is actually a pointer to the actual object in memory. Calling RemoveLocation/DestroyGroup frees that memory. Now when you assign the variable to a new UnitGroup the one it was originally pointing to is lost to the void - there is nothing pointing to it and no way for you to get it to destroy it. But it is still there, taking up a small amount of memory and even if you want to clean it up you cant because you've lost track of it by reassinging the variable. When WC3 loses track of millions of Locations (or Unitgroups, or SFX...) they start taking up a considerable amount of memory, possibly forcing Windows to use virtual memory and resulting in grinding performance. Memory leaking is rarely a problem on machines with 512MB of ram because theres a nearly limitless supply of memory, but on a machine with 128MB it's the difference between playable and laggy as hell, on a low memory system every object leaked ends up paged to the harddrive (disk chatter, slow), then when the game ends and WC3 automatically cleans up all the memory leaks, the leaked memory has to be paged back from the harddrive to the memory - resulting in the large lag at the end of games. In reality only triggers that run very often can leak a significant amount of memory, triggers on rapid periodics, "unit dies", "unit is attacked", "unit uses an ability" etc are the main ones to clean up. A couple of locations leaked in your map initlization trigger is not going to matter. |
| 01-09-2004, 06:55 PM | #7 |
Are you sure of that grater? It's not very hard to write a "smart" pointer class, which seems like the logical thing for blizzard to have done...'course I haven't tested it so... |
| 01-09-2004, 09:12 PM | #8 |
I'm very sure that blizzard does not use a smart pointer class or garbarge collection - except for emergency garbage collection and I'm not sure what exactly that cleans up. The simplist way to prove what I say is to create a very simple trigger: Code:
Leak like crazy
Events
Time - Every 0.50 seconds of game time
Conditions
Actions
For each (Integer A) from 1 to 5000, do (Actions)
Loop - Actions
Set TempLoc = (Position of Peasant 0001 <gen>)
[color=grey]Custom script: call RemoveLocation(udg_TempLoc)[/color]Try it with and without the Custom Script action enabled, if using Win2K or WinXP compare memory usage by using the Task Manager. Also note how much longer it takes to leave the game without the remove action. (You'll only need to stay in the game for about 20 seconds to get a very noticable effect) For me it leaks about 90,000KB in 25 seconds, when the destroy action is enabled it "leaks" about 600KB in 600 seconds (the leaking version would crash long before getting to 600 seconds) |
| 01-09-2004, 09:33 PM | #9 |
So if a spell does a set target unit of ability being cast = Spelltarget, for instance, and you cast the spell a second time, it just loses track of the first one and it takes up memory? Or does it not work that way with specific units? Also, if you have a Pick every unit going on a periodic timer, then every time it repicks, it stores the old one and eventually fills up memory? |
| 01-09-2004, 09:48 PM | #10 |
Not working that way for me grater. My trigger: Code:
Melee Initialization
Events
Time - Every 0.50 seconds of game time
Conditions
Actions
For each (Integer A) from 1 to 5000, do (Actions)
Loop - Actions
Set tmp = (Region centered at (Position of Peasant 0000 <gen>) with size (100.00, 100.00))
Custom script: call RemoveRect(udg_tmp)I used RemoveRect because RemoveLocation gave a compile error. (something about it not accepting a rect...I dunno where blizzard hid blizzard.j in the new version or I'd go look at what it wants...) Both with and without the last line it leaks memory at about the same rate(100,000k after 30 sec)...However, I'll agree with you that war3 doesn't have any automatic clean up... |
| 01-09-2004, 09:58 PM | #11 |
Well, for one, his trigger was creating a location, or point, not a region, so that has something to do with it. And thanks for the info, I'll be sure to do temppoints now :D |
| 01-09-2004, 10:04 PM | #12 |
Oh, was thinking he meant region when he said location...from SC Using regions and removerect does not affect memory usage, at least it didn't for me. Using points and removelocation does reduce memory usage, however. |
| 01-10-2004, 12:44 AM | #13 | ||
Quote:
Quote:
You can use as many "pick every unit" actions in unit group global variables as you like without any problems at all. Code:
Set i = (Number of units in (Units owned by Player 1 (Red))) If for example you decide to manually keep track of a players units with something like this (not that it's nessecary): Code:
Unit Enters
Events
Unit - A unit enters (Playable map area)
Conditions
(Owner of (Triggering unit)) Equal to Player 1 (Red)
Actions
Unit Group - Add (Triggering unit) to PlayerOnesUnits
Unit Dies
Events
Unit - A unit owned by Player 1 (Red) Dies
Conditions
Actions
Unit Group - Remove (Dying unit) from PlayerOnesUnitsIt is when you do something like: Code:
Unit Group - Pick every unit in (Units owned by Player 1 (Red) matching (((Matching unit) is alive) Equal to True)) and do (Actions) Now blizzard implementated a hack to help solve memory leaks, adding the line: set bj_wantDestroyGroup = true before various unit group actions will clean up the memory leak (then reset wantDestroyGroup to false). Note usage: RIGHT Code:
Custom Script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units owned by Player 1 (Red) matching (((Matching unit) is alive) Equal to True)) and do (Actions)
...DISASTER Code:
Custom Script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (PlayerOnesUnits) and do (Actions)
...Cleaning up "memory leaks" that arent memory leaks result in very frustrating bugs. This is one reason why those "in the know" about memory leaks are so relucatant to share the know, if newbies start adding "set bj_WantDestroyGroup=true" will-nilly before their pick every unit actions then they will break their triggers [then come crying to the forums]. I was stumped for days after accidentely "fixing" a "memory leak" caused my triggers to stop working, and I've had years of programming experience in c and c++. How is a total newbie possibly meant to be able to get it right? So blizzard isn't really holding out on the GUI users by neglecting to add "RemoveLocation, DestroyGroup" actions to the GUI or even explain about them. And the JASS folk mostly contain the memory leak discussion to the AI/JASS forum for much the same reason. (The reason is probably something like "It's easier to simply accept laggy but working maps than to deal with confused newbies with broken maps...") |
| 01-10-2004, 03:26 AM | #14 |
Thanks a bunch that cleared a lot up. :foot: Just one more question: Is it as simple as a unit group that doesnt have any global variables involved and uses something that creates a copy of a number of units is safe to use that destroy hack? |
| 01-11-2004, 05:33 AM | #15 |
If theres no unit group variables involved it is always safe to use the hack. Also some with unit group variables are safe (mainly if it doesn't make sense to use a temporary unit group as one of the variables) Safe: Code:
Unit Group - Add all units of (Units of type Footman) to TempGroup Retarded: Code:
Unit Group - Add all units of TempGroup to (Units of type Footman) Safe, but only cleans up one group leaving one to leak. The only way to make this action not leak is to use global (or local) unit group variables and DestroyGroup. Code:
Unit Group - Pick every unit in (Random 4 units from (Units of type Footman)) and do (Actions) |
