HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Is RemoveSomeHandle() a laggy function?

03-08-2004, 08:42 PM#1
Squashy
I've been trying to get to the root of lagginess on my map. I have two questions.

First Question:
Will this function leak two locations?
Code:
function distanceBetweenUnits takes unit a, unit b returns real
    return DistanceBetweenPoints(GetUnitLoc(a),GetUnitLoc(b))
endfunction

Second Question:
When using the RemoveWhatever() functions, are they in any interesting way more laggy than other functions? I would assume they'd take very little time to process.
03-08-2004, 11:12 PM#2
AIAndy
Yes, your function will leak 2 locations.
I did not encounter lag with the Remove functions yet (at least not the ones for objects that do not have a visual representation in the game).
03-09-2004, 05:25 AM#3
Cacodemon
Yes, it leaks so you should use two local handles then destroy them.

A little notice: When destroying object, its handle IS NOT set to null!!!
03-09-2004, 03:13 PM#4
dataangel
You want to do this:

Code:
function distanceBetweenUnits takes unit a, unit b returns real
    local location a = GetUnitLoc(a)
    local location b = GetUnitLoc(b)
    local integer temp = DistanceBetweenPoints(a, b)  

    call RemoveLocation(a)
    call RemoveLocation(b)

    return temp
endfunction
03-09-2004, 06:45 PM#5
Cubasis
Quote:
Originally Posted by dataangel
You want to do this:

Code:
function distanceBetweenUnits takes unit a, unit b returns real
    local location a = GetUnitLoc(a)
    local location b = GetUnitLoc(b)
    local integer temp = DistanceBetweenPoints(a, b)  

    call RemoveLocation(a)
    call RemoveLocation(b)

    return temp
endfunction

And as CacoDemon pointed out, you should also in the end set your handle-variables to null, like this

Code:
     .....
     call RemoveLocation(b)
     set a = null
     set b = null

     return temp
endfunction
03-09-2004, 10:29 PM#6
AIAndy
Since you want a real returned your temp variable should be real and not integer
03-12-2004, 12:07 AM#7
Squashy
Could someone explain to me the purpose of setting a handle to null after it is used? I understand exactly why you need to destroy/remove a handle, but why set to null?
Code:
function blah takes nothing returns nothing
  local location L = Location(0,0)
 
  call RemoveLocation(L)
 
  set L = null  // why this?
endfunction

In my mind, I equate handles with pointers. Therefore, I assume that Removing / Destroying a handle, like RemoveLocation() or DestroyGroup() only gets rid of what the handle points to. In effect, wouldn't that mean the handle would then point to nothing? Perhaps we are getting rid of the address that the handle stores? Where am I off in my thinking?
03-12-2004, 01:53 AM#8
AIAndy
Tests have shown that not doing this leaks. The reason as I see it is the following:
To avoid giving the script direct access to memory, every handle only points to a place on the handle array. That is a kind of intermediate object that also serves as a tombstone once the object it references is destroyed. To destroy it once there is no more reference to it from the script, reference counting is implemented. That should actually work quite fine but unfortunately there is a bug in there. The reference counter is not properly reduced for local variables at the end of their lifetime (although it is reduced when you set it to something else). That means that the above code leaks a point on the handle array if you do not set L = null.
03-12-2004, 02:56 AM#9
Squashy
What about if a function passes in a handle, like so:

Code:
function blah takes unit u returns nothing
 ... 
 //do stuff with the unit

  set u = null // do we need this?
endfunction

function bleh takes nothing returns nothing
  local unit bob = CreateUnitAtLoc(...)

  call blah(bob)
  set bob = null
endfunction

I think we need to do it, because pointer "u" is just a copy of pointer "bob", therefore it is another handle out in memory. I get this thinking mainly from the information here.
03-12-2004, 09:46 AM#10
Cubasis
Quote:
Originally Posted by Squashy
What about if a function passes in a handle, like so:

Code:
function blah takes unit u returns nothing
... 
//do stuff with the unit
 
set u = null // do we need this?
endfunction
 
function bleh takes nothing returns nothing
local unit bob = CreateUnitAtLoc(...)
 
call blah(bob)
set bob = null
endfunction

I think we need to do it, because pointer "u" is just a copy of pointer "bob", therefore it is another handle out in memory. I get this thinking mainly from the information here.
Yes, that's correctly thought of you, although we (well, I) don't really care for the unit objects, as I'm not even sure de-referencing them does any good at all. However, it can very well be. But they are most-often long-existing objects, and then will likely collect alot of different references on their life-time, and de-referencing it everywhere in the script would be kinda hard to do, as one non-de-referencing function would then ruin all your intentions.

And ofcourse, you don't create nearly the same ammount of units as you create locations or unit-groups (unless you're doing a TD....or a TS or sumtin)

It's easier/more-important to keep de-referencing locations and groups thus.

The biggest trouble/buggyness is when it comes to returning objects...

The returned Local variable does not get de-referenced if you return it. Thus.....all blizzard.j functions like...PolarProjection ....will leak a handle-array-element. This may shock you, it did me, but yeah. So if you're using PolarProjection alot, then you may wanna...switch to x/y, or CnP the polarprojection function into your script, and put the return rather into a global variable.

Code:
function GooGoo takes unit whatunit returns location
local location doo
doo = GetUnitCenter(whatunit)
return doo // <-- This reference would then leak.
endfunction

Anyways, hope that helped.

Cubasis
03-12-2004, 01:55 PM#11
Vexorian
Code:
function DistanceBetweenUnits takes unit a, unit b returns real
    return SquareRoot( Pow(GetUnitX(b)-GetUnitX(a),2) +  Pow(GetUnitY(b)-GetUnitY(a),2))
endfunction

Edit: Cubasis are you saying that functions that return locations leak? time to change a lot of stuff in my map again.
03-12-2004, 03:38 PM#12
Cubasis
Quote:
Originally Posted by Lord Vexorian

Edit: Cubasis are you saying that functions that return locations leak? time to change a lot of stuff in my map again.

Well, That's what everything implies. PolarProjection was a popular subject to the "leaking" functions discussion. And the last few days, I thought it was becouse it returned a local variable (that thus does not get de-referenced). But that doesn't seem to be the case. Here is the PolarProjection function:

Code:
function PolarProjectionBJ takes location source, real dist, real angle returns location
	local real x = GetLocationX(source) + dist * Cos(angle * bj_DEGTORAD)
	local real y = GetLocationY(source) + dist * Sin(angle * bj_DEGTORAD)
	return Location(x, y)
endfunction

As one can see, it does not actually "return" a local variable, but let's do logical changes to this function:

Code:
function PolarProjectionBJ takes location source, real dist, real angle returns location
	local real x = GetLocationX(source) + dist * Cos(angle * bj_DEGTORAD)
	local real y = GetLocationY(source) + dist * Sin(angle * bj_DEGTORAD)
	set source = null
	return Location(x, y)
endfunction

With my current logic, this would mean no handle-array-element-leak. If this is all one needs to do to avoid returned handle-leaks (in the handle-array), then one can just convert the location-to-return into 2 local reals, and return a fresh location with them.

This is kinda cool, as I had been hearing about the in-avoidability of return handle-leaks. But this is so simple, same with groups. With groups you would never return them, but instead "edit" a passed group-object or sumtin.

Cubasis
03-12-2004, 07:00 PM#13
Vexorian
I thought PolarProjection Was leak friendly because it takes 2 locations and returns a new one, nothing that couldn't be fixed by some removelocations
03-16-2004, 10:45 PM#14
jmoritz
Please note that handle leaks are very very small compared to object leaks. It leaks only a few bytes, so only if you run a big loop very often will you notice memory usage going up. Most of the times setting handles to null isn't worth the effort.
03-17-2004, 08:09 AM#15
Cubasis
Quote:
Originally Posted by jmoritz
Please note that handle leaks are very very small compared to object leaks. It leaks only a few bytes, so only if you run a big loop very often will you notice memory usage going up. Most of the times setting handles to null isn't worth the effort.

In my tests, each handle leaked was cirka 40 kb's in size (which I find kinda surprisingly big). However, as I have said before, while object-leakage happens every time you create and lose track of a object...handle-leak happens only once per local handle variable per function.

Cubasis