• 🏆 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!

Automatic Memory Leak Destroyer

this system is too cool to be real!!

Wow, this is probably the greatest thing to happen for GUI users in the history of WC3 modding. My hat is off to you

You shall soon become a god amongst GUI users

Too bad it didn't come out years ago.

This is an Automatic memory Leak Destroyer!
It catches all the memory leaks you cause by using locations/groups or effects in GUI and destroys them automatically.

There is just one thing you have to care about when using this:
Each variable that you use, filled with a group, a location or an effect, that has
to be filled for more than CLEAN_UP_INTERVAL seconds, has to be protected with
a simple function:

call ProtectHandle(udg_###)

where ### stands for the variable name.

Note: This gives DoNothing a sense.
When you call DoNothing, the destroy thread is started and the caught data are destroyed after CLEAN_UP_INTERVAL seconds, ignoring if the number of caught handles is bigger than MIN_LEAK_NUMBER.
Normally you never have to use it, but you can do so.

So to make it clear:
Memory leaks caused by things like this:



are cleared automatically!
And not only things like this, all leaks.
This can also be used as an addition to your own leak cleaning, if you forgot something.
It wont break, when you destroy your leaks on your own


This is the code:

JASS:
library MemoryLeakHelper initializer Init requires Table
// ==================================
// Give credits to Mr.Malte when used!
//===========================================================================
// Information: 
//==============
//
//  There are things called 'memory Leaks'. When you create a group or use a location
//  without destroying it, you will cause lag that stays in the whole game.
//  If you implement this library into your map it will automatically fix a big part
//  of those memory leaks, so reduce the lag extremely.
//  This should mainfully be used by GUI-users because the system is designed for them.
//
//  Of course no system can work totally automatically.
//  But there is only one thing you have to do in order to prevent bugs:
//  If you make groups or locations that have to be filled for more than CLEAN_UP_INTERVAL seconds
//  you have to save them with the code:
//
//  call ProtectHandle(XXX)
//
//  Where XXX is filled with your variable. Otherwise that variable gets destroyed
//  automatically. You can also fill in XXX with
//
//  GetLastCaughtHandle()
//
//  But if you save the things in a variable, I'd recommend to directly put the 
//  variable into the brackets. Note: GUI variables have the prefix 'udg_' in JASS.
//
//     This gives the 'Do Nothing' function in GUI a sense!
//     When you call DoNothing, all data that were caught by this system
//     will be destroyed in CLEAN_UP_INTERVAL seconds, ignoring how big
//     the number of caught handles is. This will not work, if the system is
//     already cleaning up.
//===========================================================================
// Implementation: 
//===============
//
//  The easiest thing is to directly implement this thing into your map, when you start making
//  it, so you don't have to look over your globals and use ProtectHandle on them.
//  These are the steps you have to do to clear the memory leaks:
//
//  1. Download a tool called 'JassNewGen', and unpack it somewhere. You need that
//     edit to use this tool. The 'JassNewGen' is used very commonly and offers other
//     nice features. You can find it at:
//     [url]http://www.wc3c.net/showthread.php?t=90999[/url]

//  2. Make a new trigger, and convert it to custom text. Insert everything
//     the library contains into that trigger.
//
//  3. Download a system called 'Table' from this link:
//     [url]http://www.wc3c.net/showthread.php?t=101246[/url]
//     Do the same installation stuff for 'Table' as for this system.
//
//  4. Save your map and enjoy :-)
//    
//  Note: Instead of doing 2 and 3 you can also copy and paste the folder 'MemoryLeakHelper' 
//        from the example map.
//===========================================================================
// How bad are memory leaks? 
//==========================
//  If you don't remove memory leaks, they suck memory:
//
//  Location:  0.361 kb
//  Group:     0.62 kb + 0.040 kb for each unit in the group.
//  Effect:    11.631 kb
// 
// Both, locations and groups are used very frequently. So when you don't fix those memory leaks,
// you will experience lag.

//        When you want to see, how useful this is for your map, implement it
//        and write 'call DisplayLeaks()' into a custom script that is fired when
//        they game ends.
//===========================================================================
// Changelog:
//===========
// v1.00 --- first version
// v1.01 --- able to detect special effects, too now.
// v1.02 --- made the system safer and reduced the number of variables to protect greatly.
// v1.03 --- Gave a sense to 'DoNothing'* GUI function and made the Pass Data part
//           more accurate, so the time until data get destroyed are much more explicit
//           now.
//
// *if you don't want it to be hooked, put // before line 341.
//===========================================================================
// FAQ:
// ====
//  1. Why don't you hook functions like GetLocationX or the ForGroup without BJ?
//
//      Answer: Well, in jass you would never destroy groups, rather have one global group
//              and clear/recycle it. But GUI always creates new groups with the functions.
//              So actually, jass groups don't have to be destroyed.
//              And special effects are mostly instantly destroyed and locations are never used.
//              So I don't want to endanger breaking jass systems, I rather make it for GUI, where it is
//              really useful and neccessary
//
//  2. Why should I protect my variables instead of killing my leaks?
//
//      Answer: In GUI, unitgroup effect and location variables are actually just used
//              for destroying stuff. It is rare that you really want to keep the groups.
//              So in fact, it is like one-hundred times less frequent that you want to keep
//              your data instead of destroying it.
//
//  3. I can't use jass. How can this system be useful for me?
//
//      Answer: This system works mainly automatically; You just have to use jass very rarely (and then a simple function).
//              The functions you need are:
//
//                  ProtectVariable(udg_###)
//                  GetLastCaughtHandle()
//
//              where ProtectVariable saves something you want to keep from getting destroyed. Just replace ### with your
//              variable name. NOTE: You don't have to protect the variable, when you want to keep the data inside less than
//              CLEAN_UP_INTERVAL seconds.
//
//              and where GetLastCaughtHandle responses to the handle* that was used lastly.
//              That can be for example the point where you just spawned a unit.
//              
//      * 'handle' means a specialeffect, a location or a unitgroup
//
//  4. If you give functions like 'DelayMMH', why don't you add functions like 'Disable/EnableMMH'?
//
//      Answer: Well, I want to protect the user. You do not need Disable/Enable functions.
//              To me the danger is too big, that you forget to activate it again or do
//              something like that. DelayMMH is totally enough if you don't want this system
//              to affect the code that comes next. Also that prevents, that there are
//              spells like 'Trojan Horses' that get too much access to this and can
//              change it's infrastructure.
//
//===========================================================================
// Functions:
//==========
// ProtectHandle              : Saves a handle from getting destroyed 
// ProtectVariable            : Same.
// DoNothing()                : Destroys all data caught by the system right now in X seconds.
// DelayMMD()                 : Stops the system working until the trigger ends/next wait *
//
// * This is as fast as an automatic memory leak destroyer can get. Why should
// you want to disable the system? Because it offers the possibilty to make things
// more efficient. I don't want to say, this is unefficient, because it is not.
// But this will destroy leaks like 10% slower.
//
//===========================================================================


    globals
        // The system fires when you do something that creates a leak.
        // The data that cause leak are saved in a variable then.
        // And every CLEAN_UP_INTERVAL seconds those data are destroyed.
        // This shouldn't be too high, or too low.
        private constant real CLEAN_UP_INTERVAL = 20.
        // If this is set to true, the system will work more slowly (but you wont notice)
        // and count, how much memory this system was able to save.
        // This value is display by the function DisplayLeaks() then.
        // WARNING: This sucks a lot of performance. I would ONLY use it when you want
        // to test, if this is useful for your map. Later set it to false.
        private constant boolean DISPLAY_SAVED_MEMORY = false
        // The Data are only cleaned up, when that many handles were caught
        private constant integer MIN_LEAK_NUMBER = 1750
        // How often are data passed to the destroyer?
        // Leaks stay for a random time between CLEAN_UP_INTERVAL and CLEAN_UP_INTERVAL+PASS_INTERVAL
        // in the game
        private constant real PASS_INTERVAL = 2.5
    endglobals
    
    globals
        private HandleTable IndexData
        private HandleTable IsSaved
        
        //! textmacro MemoryLeakVars takes NAME, TYPE
        private integer Caught$NAME$Leaks = 0
        private $TYPE$ array $NAME$LeakData
        private integer $NAME$DestroyCount = 0
        private $TYPE$ array $NAME$DestroyData
        //! endtextmacro
        //! runtextmacro MemoryLeakVars("Location","location")
        //! runtextmacro MemoryLeakVars("Effect","effect")
        //! runtextmacro MemoryLeakVars("Group","group")
        
        
        private integer DestroyedLeaks = 0
        private integer CaughtLeaks = 0
        private integer DestroyedLeaksUser = 0
        private handle LastCaught
        private timer PassTimer = CreateTimer()
        private timer CleanTimer = CreateTimer()
        private timer DelayTimer = CreateTimer()
        private boolean IsDestroying = false
        private real SavedMemory = 0.
        private real LastCheckedGroupMemoryUsage = 0.
        private boolean DestroyThreadRunning = false
        private boolean Disabled = false
        
        // These values were found out in a big leak test by gekko.
        private constant real LOCATION_MEMORY_USAGE        = 0.361
        private constant real GROUP_MEMORY_USAGE           = 0.62
        private constant real GROUP_UNIT_MEMORY_USAGE      = 0.040
        private constant real EFFECT_MEMORY_USAGE          = 11.631
        private constant real REMOVED_EFFECT_MEMORY_USAGE  = 0.066
    endglobals
    
    // ======================================
    // ============= Basic Code =============
    // ======================================
    
    function GetLastCaughtHandle takes nothing returns handle
        return LastCaught
    endfunction
    
    function ProtectHandle takes handle h returns nothing
        set IsSaved[h] = 1
    endfunction
    
    function ProtectVariable takes handle h returns nothing
        set IsSaved[h] = 1
    endfunction

    private function EnableMMH takes nothing returns nothing
        set Disabled = false
    endfunction

    function DelayMMH takes nothing returns nothing
        set Disabled = true
        call TimerStart(DelayTimer,0.00,false,function EnableMMH)
    endfunction
    
    function DisplayLeaks takes nothing returns nothing
        call ClearTextMessages()
        call BJDebugMsg("======= MemoryLeakHelper =======")
        call BJDebugMsg("Destroyed Leaks: "+I2S(DestroyedLeaks))
        call BJDebugMsg("Destroyed Leaks by user: "+I2S(DestroyedLeaksUser))
        call BJDebugMsg("Percentage System: "+R2S(I2R(DestroyedLeaks)/I2R(DestroyedLeaks+DestroyedLeaksUser)*100.)+"%")
        call BJDebugMsg("Percentage User: "+R2S(I2R(DestroyedLeaksUser)/I2R(DestroyedLeaks+DestroyedLeaksUser)*100.)+"%")
        call BJDebugMsg("Leaks until next destroy: "+I2S(MIN_LEAK_NUMBER-CaughtLeaks))
        call BJDebugMsg(" === In Destroy Queue === ")
        call BJDebugMsg("   Group Leaks: "+I2S(GroupDestroyCount))
        call BJDebugMsg("   Location Leaks: "+I2S(LocationDestroyCount))
        call BJDebugMsg("   Effect Leaks: "+I2S(EffectDestroyCount))
        call BJDebugMsg(" === Not in Destroy Queue yet === ")
        call BJDebugMsg("   Group Leaks: "+I2S(CaughtGroupLeaks))
        call BJDebugMsg("   Location Leaks: "+I2S(CaughtLocationLeaks))
        call BJDebugMsg("   Effect Leaks: "+I2S(CaughtEffectLeaks))
        call BJDebugMsg("Time until next PassSequence: "+I2S(R2I(TimerGetRemaining(PassTimer)+0.5))+" seconds.")
        call BJDebugMsg(" ")
        if DISPLAY_SAVED_MEMORY then
            call BJDebugMsg("All in all the MemoryLeakHelper could release "+R2S(SavedMemory)+" kb of memory.")
        endif
        call BJDebugMsg("================================")
    endfunction
    
    private function GroupGetMemoryUsageEnum takes nothing returns nothing
        set LastCheckedGroupMemoryUsage = LastCheckedGroupMemoryUsage + GROUP_UNIT_MEMORY_USAGE
    endfunction
    
    function GroupGetMemoryUsage takes group g returns real
        set LastCheckedGroupMemoryUsage = 0.
        call ForGroup(g,function GroupGetMemoryUsageEnum)
        return LastCheckedGroupMemoryUsage + GROUP_MEMORY_USAGE
    endfunction
    
    //! textmacro ResponseOnLeak takes NAME, VALUE
    private function Catch$NAME$ takes $VALUE$ l returns nothing
        set LastCaught = l
        
        if Disabled then
            return
        endif
        
        if IndexData.exists(l) == false then
            //call BJDebugMsg("Caught $NAME$")
            set Caught$NAME$Leaks = Caught$NAME$Leaks + 1
            set $NAME$LeakData[Caught$NAME$Leaks] = l
            set IndexData[l] = Caught$NAME$Leaks
        endif
    endfunction
    
    private function AddTo$NAME$DestroyQueue takes $VALUE$ l returns nothing
        set $NAME$DestroyCount = $NAME$DestroyCount + 1
        set $NAME$DestroyData[$NAME$DestroyCount] = l
        set IndexData[l] = $NAME$DestroyCount*-1 // Put his to negative, so we know that this is used in the DestroyQueue now.
    endfunction
    
    private function Release$NAME$ takes $VALUE$ l returns nothing
        local integer index
        if IsDestroying == false and IndexData.exists(l) then
            set index = IndexData[l]
            // If this is true, the index wasn't put to a destroy queue yet.
            if index > 0 then
                set $NAME$LeakData[index] = $NAME$LeakData[Caught$NAME$Leaks]
                set Caught$NAME$Leaks = Caught$NAME$Leaks - 1
            else
                set index = index * -1
                set $NAME$DestroyData[index] = $NAME$DestroyData[$NAME$DestroyCount]
                set $NAME$DestroyCount = $NAME$DestroyCount - 1
            endif
            call IndexData.flush(l)
            set DestroyedLeaksUser = DestroyedLeaksUser + 1
        endif
    endfunction
    //! endtextmacro
    //! runtextmacro ResponseOnLeak("Location","location")
    //! runtextmacro ResponseOnLeak("Group","group")
    //! runtextmacro ResponseOnLeak("Effect","effect")
    
    private function DestroyMemoryLeaks takes nothing returns nothing
        set IsDestroying = true
        
        //call BJDebugMsg("DESTROYING Memory Leaks")
        //! textmacro DestroyLeaks takes NAME, DESTROYCALL, MEMORYUSAGE
        set DestroyedLeaks = DestroyedLeaks + $NAME$DestroyCount
        loop
            exitwhen $NAME$DestroyCount == 0
            
            if DISPLAY_SAVED_MEMORY then
                set SavedMemory = SavedMemory + $MEMORYUSAGE$
            endif
            
            call $DESTROYCALL$($NAME$DestroyData[$NAME$DestroyCount])
            call IndexData.flush($NAME$DestroyData[$NAME$DestroyCount])
            set $NAME$DestroyCount = $NAME$DestroyCount - 1
        endloop
        //! endtextmacro
        //! runtextmacro DestroyLeaks ("Group","DestroyGroup","GroupGetMemoryUsage(GroupDestroyData[GroupDestroyCount])")
        //! runtextmacro DestroyLeaks ("Location","RemoveLocation","LOCATION_MEMORY_USAGE")
        //! runtextmacro DestroyLeaks ("Effect","DestroyEffect","EFFECT_MEMORY_USAGE")
        
        set IsDestroying = false
        set DestroyThreadRunning = false
        //call StartPassTimer.execute() // Strange. This causes bugs sometimes and the function isn't called
        // This is slower, but safe.
        call ExecuteFunc("StartPassTimer")
    endfunction
    
    function StartDestroyThread takes nothing returns nothing
        if DestroyThreadRunning == false then
            set DestroyThreadRunning = true
            call TimerStart(CleanTimer,CLEAN_UP_INTERVAL,false,function DestroyMemoryLeaks)
            call PauseTimer(PassTimer)
        endif
    endfunction
    
    hook DoNothing StartDestroyThread
    
    // We want that the user doesn't have to protect too many variables, but all the variables that are filled longer
    // than CLEAN_UP_INTERVAL seconds. But what, when the handle thing is put into the destroy stack and the next destroy is
    // in 5 seconds, because the last one was 15 seconds ago? We can simply avoid something like that by using a 2-step-system
    // that goes sure, the handle is only destroyed when it passed the CLEAN_UP_INTERVAL twice.
    // Having two kinds of variables is simply easier and more efficient than having another variable that refers to
    // how many times the handle passed the timer; If it isn't passed/cleared in the Interval then, we can't loop
    // that easily through the data and we'd have to fix gaps later; That would suck a lot of performacne.
    private function PassMemoryLeaks takes nothing returns nothing
        //call BJDebugMsg("PassMemoryLeaks")
        //! textmacro PassLeaks takes NAME
        set CaughtLeaks = CaughtLeaks + Caught$NAME$Leaks
        //call BJDebugMsg("Caught $NAME$s: "+I2S(Caught$NAME$Leaks))
        loop
            exitwhen Caught$NAME$Leaks < 1
            if IsSaved.exists($NAME$LeakData[Caught$NAME$Leaks]) == false and $NAME$LeakData[Caught$NAME$Leaks] != null then
                call AddTo$NAME$DestroyQueue($NAME$LeakData[Caught$NAME$Leaks])
            endif
            set $NAME$LeakData[Caught$NAME$Leaks] = null
            set Caught$NAME$Leaks = Caught$NAME$Leaks - 1
        endloop
        //! endtextmacro
        //! runtextmacro PassLeaks ("Group")
        //! runtextmacro PassLeaks ("Location")
        //! runtextmacro PassLeaks ("Effect")
        
        if CaughtLeaks > MIN_LEAK_NUMBER then
            set CaughtLeaks = 0
            //call BJDebugMsg("Caught Leaks: "+I2S(MIN_LEAK_NUMBER))
            //call BJDebugMsg("Now start Destroy Timer")
            set DestroyThreadRunning = true
            call TimerStart(CleanTimer,CLEAN_UP_INTERVAL,false,function DestroyMemoryLeaks)
            // We have to pause this timer a bit; Otherwise it would break the CLEAN_UP_INTERVAL rule.
            call PauseTimer(PassTimer)
        endif
        
    endfunction
    
    // =================================
    // ============= Usage =============
    // =================================
    
    private function PP takes location source, real dist, real angle returns nothing
        call CatchLocation(source)
    endfunction
    
    private function CU takes integer count, integer unitId, player p, location l, real face returns nothing
        call CatchLocation(l)
    endfunction
    
    private function IPO takes unit k, string order, location l returns nothing
        call CatchLocation(l)
    endfunction
    
    private function SUP takes unit who, location l returns nothing
        call CatchLocation(l)
    endfunction
    
    private function SUF takes unit who, location l, real dur returns nothing
        call CatchLocation(l)
    endfunction
    
    private function GUR takes real radius, location l, boolexpr filter returns nothing
        call CatchLocation(l)
    endfunction
    
    private function CUF takes integer count, integer unitId, player whichPlayer, location loc, location lookAt returns nothing
        call CatchLocation(loc)
        call CatchLocation(lookAt)
    endfunction
    
    hook PolarProjectionBJ PP
    hook CreateNUnitsAtLoc CU
    hook CreateNUnitsAtLocFacingLocBJ CUF
    hook IssuePointOrderLocBJ IPO
    hook SetUnitPositionLoc SUP
    hook SetUnitFacingToFaceLocTimed SUF
    hook GetUnitsInRangeOfLocMatching GUR

    hook RemoveLocation ReleaseLocation
    
    
    private function FG takes group g, code callback returns nothing
        call CatchGroup(g)
    endfunction
    
    hook ForGroupBJ FG // :D This should catch all GUI usages for groups.
    hook GroupPickRandomUnit CatchGroup
    hook CountUnitsInGroup CatchGroup
    
    hook DestroyGroup ReleaseGroup
    
    private function ASETU takes string bla, widget d, string blu returns nothing
        // We can not catch THIS effect, but the effect that was created before.
        // So we can destroy all SpecialEffects excpet one.
        call CatchEffect(GetLastCreatedEffectBJ())
    endfunction
    
    private function ASE takes location where, string modelName returns nothing
        call CatchLocation(where)
        call CatchEffect(GetLastCreatedEffectBJ())
    endfunction

    hook AddSpecialEffectLocBJ ASE
    hook AddSpecialEffectTargetUnitBJ ASETU
    hook DestroyEffect ReleaseEffect
    hook DestroyEffectBJ ReleaseEffect
    
    // When I want to make the timer run the PassMemoryLeaks things, I have to use an .execute command which requires an extra func.
    function StartPassTimer takes nothing returns nothing
        //call BJDebugMsg("Restarting PassTimer")
        call TimerStart(PassTimer,PASS_INTERVAL,true,function PassMemoryLeaks)
    endfunction
    
    private function Init takes nothing returns nothing
        set IndexData = HandleTable.create()
        set IsSaved = HandleTable.create()
        call StartPassTimer()
    endfunction
endlibrary

This uses Table by Vexorian!

Keywords:
memory, leaks, vjass, mui, gui, system, ,
Contents

MemoryLeakHelper (Map)

Reviews
10:10, 26th Sep 2009 The_Reborn_Devil: The code looks good and I couldn't see any leaks or other problems. This is definitely useful for GUI users. Approved Rating: Recommended I might change it to Highly Recommended.

Moderator

M

Moderator

10:10, 26th Sep 2009
The_Reborn_Devil:

The code looks good and I couldn't see any leaks or other problems. This is definitely useful for GUI users.
Approved
Rating: Recommended
I might change it to Highly Recommended.
 
Level 15
Joined
Jul 19, 2007
Messages
618
i was wondering how u did that without hooks! but u did it with hooks...

this is quite good for this people who made there maps long ago but have a lot of leaks in GUI or for thous who really dont know and cant learn what leaks are and how to handle them.

there is no bad thing about ur system for such peaople, but u should know that one hook generates quite a lot of lines as well as triggers, actions, condtions... all that stuff global variables, a lot of custom functions...

and you really have a lot of hooks so this is only good for thous who have old maps with bad GUI code and are lazy to fix that... however hooks affect the whole map and systems/librarys made by other people... and if for exaple some spells use destroy effect a lot of times you might have an lag, coz DestroyEffect will now become h_DestroyEffect... and it will call hooks as triggers, depending on all that stuff...

the problem is not that insted of native BJ is called but because that BJ calls other BJ-s and triggers which are hooked... now all that gets quite slow if you would use that in my Water Explosion spell which creates a lot of water explosions every .33 seconds...

however i can say really gj its something new here and very usefull for GUI beginners.

so +rep...
Greets!
~Dark Dragon
 
Level 15
Joined
Jul 19, 2007
Messages
618
Also, to add to what DD said, instead of DisplayLeaks function... make debug msgs use vJass' "debug" keyword...
Much more useful imo.

DD says why it's such a good job :) so good job!

EDIT:
Use the "hidden" tags in your thread description for the pic and the jass ;)

Deuterium really says right thing! please use hidden tags...
and btw u have an bug... u hooked DestroyEffect but GUI uses DestroyEffectBJ so ur engine will not activate when used by GUI but by jassers which dont want that it triggers... it this example you can see that blizzard BJ-s are not useless but good in some cases...

make sure that GUI functions are hooked.
 
Level 12
Joined
Oct 16, 2008
Messages
512
I thought DestroyEffectBJ would just call DestroyEffect, which would, at this point, be hooked by his system?... maybe i'm saying bullcrap here and in that case please correct me, I just want to make sure my little JASS knowledge didnt totally go to waste in the meantime...
 
Level 15
Joined
Jul 19, 2007
Messages
618
I thought DestroyEffectBJ would just call DestroyEffect, which would, at this point, be hooked by his system?... maybe i'm saying bullcrap here and in that case please correct me, I just want to make sure my little JASS knowledge didnt totally go to waste in the meantime...

yeah ill help u explain!

there are functions from blizzard.j and common.j! if you hook one from common.j then one from blizzard.j wont be hooked... why is that so? it is because blizzard.j and common.j are constant scripts and in blizzard.j DestroyEffectBJ wont call h_DestroyEffect but DestroyEffect! hooks do not work there... maybe vexorian will
change that but as for now that is impossible...

the same reason why blizzard BJ-s dont get inlined is coz JH does not know how blizzard.j is coded, but our BJ-s get inlined if "single lined"...

Greets!
~Dark Dragon
 
Level 11
Joined
Nov 4, 2007
Messages
337
First of all, thanks for the compliments/criticism

there is no bad thing about ur system for such peaople, but u should know that one hook generates quite a lot of lines as well as triggers, actions, condtions... all that stuff global variables, a lot of custom functions...

Not many more than destroying it on your own. Destroy on your own =

set udg_Bla = XXX
call DoAnything(udg_Bla)
call Remove(udg_Bla)

And this thing makes from

call DoAnything(XXX)

local integer prot2 =XXX
call DoAnything(prot2)
call Catch(prot2)

Also, to add to what DD said, instead of DisplayLeaks function... make debug msgs use vJass' "debug" keyword...
Much more useful imo.

No, I wont. Because the user doesn't have any control, when the things are displayed then.
That func isn't called automatically by the system

u hooked DestroyEffect but GUI uses DestroyEffectBJ

Well, that's not too bad, because the data are only destroyed, if they're not 0, but
I updated it.

Finnaly, a system to clean up leaks for you.this is just pretty much perfect apart from that protecting thing

Just make sure, that CLEAN_UP_INTERVAL is bigger than the amount of seconds you want to keep the data.



All in all, I am thinking about an option to stop the memory leak destroyer working until the next wait appears or the function is finished.
So you can get this work more performant in things that run very quickly (every 0.01 seconds e.g.)
But that would make all spells require this system.
 
Level 15
Joined
Jul 19, 2007
Messages
618
yeah well i know i can directly call ur stuff but point is that people use natives and all that... btw even if i use ur functions directly hooks wont reduce... problems are the hook command they are slow as hell, nothing else quite good engine and btw as i said its not ur problem its that JassHelper generates "compiles" hooks in to jass with all that stuff so this one line hook will become: BJ-s, globals, and most of all handle-ids will increase because of objects loading...

anyway gj!
 
Level 8
Joined
Aug 4, 2006
Messages
357
this system isn't required for most maps which are good, and the bad ones are those which aren't played.
Well, I think there are a few GUI users who know how to design a good game, but do not know technical stuff like how to clear leaks. To them, this could be useful. I'm not saying they shouldn't learn how to clear leaks the real way... I just think that if people don't have the time to learn JASS or learn how to destroy leaks, they should focus their time on what really matters in a custom game: the gameplay.

Also it is enough to post it at one section, not as spell and in the Jass section.
Ya, I think he should have only posted it here in the Spell section. No one in the JASS section would use it because they all know how to get rid of leaks. On the other hand, there are a lot of people who visit the Spell section that don't know how to destroy leaks.
 
Level 11
Joined
Nov 4, 2007
Messages
337
Isn't protecting and unprotecting variables the same stuff as creating locals and destroy the leaks?

Have you ever needed a unitgroup/effect/location variable in gui?
Further, read the FAQ.
It answers your quesrion

I mean REALLY, if you do 3000 leaks in 30 seconds, it will create lagg waves which become bigger, then disappear and start again.

3000 leaks are no problem for any computer.
They're maybe 20 MB memory.

The problem is, when you create that many laggs frequently without removing them, then it will start lagging
(maybe after 25000 leaks it starts lagging heavily)
 
Level 11
Joined
Nov 4, 2007
Messages
337
Updatet to the newest version.
You have got this function now:
JASS:
function DelayMMH takes nothing returns nothing
which stops the system catching any leaks until the thread that started the function ends, or a wait appears or something like that. And wc3 does never do things at the same time. One after the other.
So you will be able to bost the performance of systems (if you really think it's necessary.. I don't) now.

Also this has got some other important changes.
 
  • Like
Reactions: Rmx
Level 19
Joined
Feb 4, 2009
Messages
1,313
why should GUI users switch to JNGP without knowing about leaks...
furthermore I agree with Anachron that it's rather pointless and there are only very few situations where it might come in use (so few that I can't really imagine any)

and I don't like the fake quotes
it makes you appear arrogant or something like that

it's a great job but as I already said:
why should GUI users use JASS except for custom script?
and probably their code is so bad that there is no other way then recoding everything
 
Level 11
Joined
Jul 2, 2008
Messages
601
I think this system is for novices at triggering... And with it they will always stay them.
Advanced users will never use this ;( Usually we need variables to use them in future and there is no difference for me to call RemoveLocation(udg_bla) or just call ProtectVariable(udg_Bla)... Never.
 
Level 11
Joined
Nov 4, 2007
Messages
337
@Aspard:
Read the FAQ. It explains, why using ProtectHandle is better than using RemoveLocation.

Advanced users will never use this? Wrong. It just makes triggering easier.
You need less time.

@DARK_G4NDALF:
GUI users would like to switch, because there are many good vJass spells they might want to use in their maps.

you don't like the fake quotes :D
Omg, they are no fakes.
Fail!

why should GUI users use JASS except for custom script?

They don't have to use more jass than normally with this. It works automatically.
Another fail :p

The most quotes are from this thread:

http://www.wc3c.net/showthread.php?t=107432
 
Level 16
Joined
Oct 12, 2008
Messages
1,570
Make an UnProtectHandle/Variable(), because you might need it at first (not destroy it), and after a while not need it anymore,,

I can't think of any good example of when it would come in handy, but some people might need it and it will complement the ProtectHandle/Variable()
 
Level 8
Joined
Aug 4, 2006
Messages
357
I'm surprised at how many people don't like this system here, especially considering that people liked it at wc3c. It's basically an automatic garbage collector. There is no reason why we should be forced to do manual garbage collection in wc3. Most people who trigger in wc3 will never go on to program in something like C++, where you need to destroy objects. So, why do they need to learn how to clear leaks? Starcraft 2 will feature a robust garbage collection system. Wc3 triggerers should not waste their time clearing leaks because now they have a system that blizzard should have put in wc3 in the first place, and clearing leaks does not teach them any vital program design concepts.

Personally, I'm going to continue clearing my own leaks in vJASS because I need the practice for C++.
 
Level 11
Joined
Nov 4, 2007
Messages
337
Why did some prick rate 1/5?

I do not understand at all why people post comments on this without reading the description/other comments or understanding what the system actually does?
This makes people lazier - so it's bad?
I'd say 'it saves time'.
You wont have to do such stupid work again.
 
Level 6
Joined
Nov 11, 2008
Messages
61
5 of 5 from me
i like it and you sure save time using this
just on question if you want t save a varible array f.x i got hero 1-10 do have to do call protect.... hero(1) and ther call protect.... hero(2) or just call protect.... Hero ?
eny way perfect system i sure se no sence so many ppl dont like it ??
 
Level 6
Joined
Mar 2, 2009
Messages
236
Blizzard should have implemented this a long time ago...
+rep and 5/5 for such an awesome system.
And to everyone else: who the hell cares if the system makes people lazy? Fixing leaks was something that mappers shouldn't have had to do in the first place.
 
Level 9
Joined
Aug 27, 2009
Messages
473
The only good thing with posting this here on the hive work shop, is the funny comments! :D
MapperMalte, this system is completely useless... Give me one situation where I or ANOTHER player can use this... system...
By keeping the leaks its possible to generate 1000's of leaks, throwing 2-3 spells with 0.3 sec timer will create 3 leaks evert 0.3 second that will make 60 leaks every second * 20 for clean up interval will store 1200 leaks in this periode! If you then add 5 players throing this spells some more times you will stay with 6000 leaks! And this is with only 1 leak each spell! Think if its 4 leaks in the spell? Then its 24000 leaks!!!
That means: LAGG!
 
Level 9
Joined
Aug 27, 2009
Messages
473
No it doesn't.
I explained it multiple times. So read!
If your computer doesn't have 10 mb of work-memory: FAIL!
Also you didn't read the feature list.

Man, you're just jealous.

Hahaha, thats why i like this thread. ;D This comment is hollariouse.

Let me explain you something:
i dont fail
why tell me to read when i tell you that its funny to read this thread?
10 mb of memory..? Its cpu, prosesor and ram im talking about.. If you got 10000 ram, tell me. Because i got 4000 on both my new computers...
And a list of feutures is ok to read, and easy to write.. But i know you wont do anything of what you have writen...
Im jalouse..? Im more jalouse of my dog, since he can wat dog food.. So, no, im not jalouse..

And now, ive listed everything in the ugly way you do it, just to make you read it..
 
Level 8
Joined
Aug 4, 2006
Messages
357
The only good thing with posting this here on the hive work shop, is the funny comments! :D
MapperMalte, this system is completely useless... Give me one situation where I or ANOTHER player can use this... system...
By keeping the leaks its possible to generate 1000's of leaks, throwing 2-3 spells with 0.3 sec timer will create 3 leaks evert 0.3 second that will make 60 leaks every second * 20 for clean up interval will store 1200 leaks in this periode! If you then add 5 players throing this spells some more times you will stay with 6000 leaks! And this is with only 1 leak each spell! Think if its 4 leaks in the spell? Then its 24000 leaks!!!
That means: LAGG!
Dude, you fail at math. 3 leaks every .3 seconds is ~10 leaks every second (not 60). Anyway, even if you make 24000 effect leaks (11 kb each) every 20 seconds, that's only 26.4 mb of RAM, which is nothing. No matter whether you clear the leaks manually or with this system, you're still going to be clearing the same amount of leaks every CLEAN_UP_INTERVAL seconds. The only difference is when the leaks are cleared. If you're experiencing lag while using this system, either you're terrible at triggering or you need to decrease CLEAN_UP_INTERVAL (or both).

This comment is hollariouse.
Yes, your lack of logic and spelling ability are indeed hilarious.

10 mb of memory..? Its cpu, prosesor and ram im talking about.. If you got 10000 ram, tell me. Because i got 4000 on both my new computers...
Uh, what exactly is the problem with using .25% of your ram? FAIL

And a list of feutures is ok to read, and easy to write.. But i know you wont do anything of what you have writen...
Im jalouse..? Im more jalouse of my dog, since he can wat dog food.. So, no, im not jalouse..

And now, ive listed everything in the ugly way you do it, just to make you read it..
The comments on this thread have officially become so stupid that it's funny. Congratulations eleljrk.
 
Top