• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[JASS] Help to solve leak problem.

Status
Not open for further replies.

Vex

Vex

Level 3
Joined
Dec 1, 2007
Messages
33
Hi.

Short description of what happens. The code will create around 173.000
special effects next to each other on the map before removing them.

What I have observed is that war3.exe use around 150MB ram when the map is started.
After the effects are created, it use around 850MB. After the 'cleanup', 722MB...

I have read through many pages and looked for answers, but didn't find anything I didn't know already.
Perhaps I just missed something :S

The effects will be replaced with other types during the game many times,
so a solution for cleaning up 100% after one ore more effects is very needed.
The code that removes the effects is just there to let me know how much it leaks.

Description of the first 3 functions and what values the global variables start with is below the code.

JASS:
function BrkCounter takes integer n returns nothing
  set udg_brkCounter = udg_brkCounter + 1
  if ( udg_brkCounter >= n ) then
    set udg_brkCounter = 0
    call TriggerSleepAction(0.01)
    call DisplayTextToForce( bj_FORCE_PLAYER[0], "." )
  endif
endfunction

function SqXtoX takes integer sqX returns real
  return I2R(-30016 + 128*sqX)
endfunction

function SqYtoY takes integer sqY returns real
  return I2R(-30272 + 128*sqY)
endfunction

function Trig_Dungeon_Generation_Actions takes nothing returns nothing
  local integer i = 0
  local integer j = 0
  local integer k = 0
  local integer sqX = 0
  local integer sqY = 0
  local effect sfx = null
  local location loc = null

  set i = 0
  loop
    exitwhen( i > 4 )
    set sqX = udg_dngSqXmin[i]
    loop
      exitwhen( sqX > udg_dngSqXmax[i] )
      set sqY = udg_dngSqYmin[i]
      loop
	exitwhen( sqY > udg_dngSqYmax[i] )
	call BrkCounter( 900 )
	set loc = Location(SqXtoX(sqX), SqYtoY(sqY))
	set sfx = AddSpecialEffectLocBJ( loc, "Doodads\\LordaeronSummer\\Terrain\\LoardaeronRockChunks\\LoardaeronRockChunks2.mdl" )
	call RemoveLocation( loc )
	set loc = null // *** No noticeable reduction of leaks. ***
	set j = R2I( udg_dngSqPlatforms / 8192 )
	set k = ModuloInteger( udg_dngSqPlatforms, 8192 )
	if ( j == 0 ) then
	  set udg_dngSqPlatform_00[k] = sfx
	elseif ( j == 1 ) then
	  set udg_dngSqPlatform_01[k] = sfx
	elseif ( j == 2 ) then
	  set udg_dngSqPlatform_02[k] = sfx
	elseif ( j == 3 ) then
	  set udg_dngSqPlatform_03[k] = sfx
	elseif ( j == 4 ) then
	  set udg_dngSqPlatform_04[k] = sfx
	elseif ( j == 5 ) then
	  set udg_dngSqPlatform_05[k] = sfx
	elseif ( j == 6 ) then
	  set udg_dngSqPlatform_06[k] = sfx
	elseif ( j == 7 ) then
	  set udg_dngSqPlatform_07[k] = sfx
	elseif ( j == 8 ) then
	  set udg_dngSqPlatform_08[k] = sfx
	elseif ( j == 9 ) then
	  set udg_dngSqPlatform_09[k] = sfx
	elseif ( j == 10 ) then
	  set udg_dngSqPlatform_10[k] = sfx
	elseif ( j == 11 ) then
	  set udg_dngSqPlatform_11[k] = sfx
	elseif ( j == 12 ) then
	  set udg_dngSqPlatform_12[k] = sfx
	elseif ( j == 13 ) then
	  set udg_dngSqPlatform_13[k] = sfx
	elseif ( j == 14 ) then
	  set udg_dngSqPlatform_14[k] = sfx
	elseif ( j == 15 ) then
	  set udg_dngSqPlatform_15[k] = sfx
	elseif ( j == 16 ) then
	  set udg_dngSqPlatform_16[k] = sfx
	elseif ( j == 17 ) then
	  set udg_dngSqPlatform_17[k] = sfx
	elseif ( j == 18 ) then
	  set udg_dngSqPlatform_18[k] = sfx
	elseif ( j == 19 ) then
	  set udg_dngSqPlatform_19[k] = sfx
	elseif ( j == 20 ) then
	  set udg_dngSqPlatform_20[k] = sfx
	elseif ( j == 21 ) then
	  set udg_dngSqPlatform_21[k] = sfx
	endif
	set sfx = null // *** No noticeable reduction of leaks. ***
	set udg_dngSqPlatforms = udg_dngSqPlatforms + 1
	set sqY = sqY + 1
      endloop
      set sqX = sqX + 1
    endloop
    set i = i + 1
  endloop
  call DisplayTextToForce( GetPlayersAll(), I2S(udg_dngSqPlatforms)+" effects created." )

  call TriggerSleepAction( 2 )
  loop
    call BrkCounter( 1000 )
    set udg_dngSqPlatforms = udg_dngSqPlatforms - 1
    set j = R2I( udg_dngSqPlatforms / 8192 )
    set k = ModuloInteger( udg_dngSqPlatforms, 8192 )
    if ( j == 0 ) then
      set sfx = udg_dngSqPlatform_00[k]
    elseif ( j == 1 ) then
      set sfx = udg_dngSqPlatform_01[k]
    elseif ( j == 2 ) then
      set sfx = udg_dngSqPlatform_02[k]
    elseif ( j == 3 ) then
      set sfx = udg_dngSqPlatform_03[k]
    elseif ( j == 4 ) then
      set sfx = udg_dngSqPlatform_04[k]
    elseif ( j == 5 ) then
      set sfx = udg_dngSqPlatform_05[k]
    elseif ( j == 6 ) then
      set sfx = udg_dngSqPlatform_06[k]
    elseif ( j == 7 ) then
      set sfx = udg_dngSqPlatform_07[k]
    elseif ( j == 8 ) then
      set sfx = udg_dngSqPlatform_08[k]
    elseif ( j == 9 ) then
      set sfx = udg_dngSqPlatform_09[k]
    elseif ( j == 10 ) then
      set sfx = udg_dngSqPlatform_10[k]
    elseif ( j == 11 ) then
      set sfx = udg_dngSqPlatform_11[k]
    elseif ( j == 12 ) then
      set sfx = udg_dngSqPlatform_12[k]
    elseif ( j == 13 ) then
      set sfx = udg_dngSqPlatform_13[k]
    elseif ( j == 14 ) then
      set sfx = udg_dngSqPlatform_14[k]
    elseif ( j == 15 ) then
      set sfx = udg_dngSqPlatform_15[k]
    elseif ( j == 16 ) then
      set sfx = udg_dngSqPlatform_16[k]
    elseif ( j == 17 ) then
      set sfx = udg_dngSqPlatform_17[k]
    elseif ( j == 18 ) then
      set sfx = udg_dngSqPlatform_18[k]
    elseif ( j == 19 ) then
      set sfx = udg_dngSqPlatform_19[k]
    elseif ( j == 20 ) then
      set sfx = udg_dngSqPlatform_20[k]
    elseif ( j == 21 ) then
      set sfx = udg_dngSqPlatform_21[k]
    endif
    call DestroyEffectBJ( sfx )
    set sfx = null // *** No noticeable reduction of leaks. ***
    exitwhen( udg_dngSqPlatforms == 0 )
  endloop
  call DisplayTextToForce( GetPlayersAll(), "Clean up complete." )

  call DestroyTrigger( GetTriggeringTrigger() ) // *** No noticeable reduction of leaks. ***
endfunction

//===========================================================================
function InitTrig_Dungeon_Generation takes nothing returns nothing
    set gg_trg_Dungeon_Generation = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Dungeon_Generation, function Trig_Dungeon_Generation_Actions )
endfunction

'BrkCounter' is a function that adds a pause every now and then in the loops. Without it, they would never finish.
'SqXtoX' and 'SqYtoY' are just functions that makes locating specific squares easier (I treat the map as a grid of 128x128 point squares).

Start values for the global variables.
Code:
  set udg_dngSqXmin[0] = 1
  set udg_dngSqXmax[0] = 80
  set udg_dngSqYmin[0] = 388
  set udg_dngSqYmax[0] = 468
  set udg_dngSqXmin[1] = 1
  set udg_dngSqXmax[1] = 228
  set udg_dngSqYmin[1] = 193
  set udg_dngSqYmax[1] = 377
  set udg_dngSqXmin[2] = 244
  set udg_dngSqXmax[2] = 468
  set udg_dngSqYmin[2] = 193
  set udg_dngSqYmax[2] = 377
  set udg_dngSqXmin[3] = 1
  set udg_dngSqXmax[3] = 228
  set udg_dngSqYmin[3] = 1
  set udg_dngSqYmax[3] = 184
  set udg_dngSqXmin[4] = 244
  set udg_dngSqXmax[4] = 468
  set udg_dngSqYmin[4] = 1
  set udg_dngSqYmax[4] = 184
 
Last edited by a moderator:

Vex

Vex

Level 3
Joined
Dec 1, 2007
Messages
33
EDIT3: In short. If I remove the effects in the first loop, they would not be visible during the game, and there would be no point in creating them in the first place. I found out just now that I don't need to cover the entire map with them, but no matter if I use just 1 or 1.000.000, they still leak. It should be possible to create a special effect at the beginning of the game, then clean up after it 5 mins later.

It lags while they are created, yes. Afterwards, it's fine.
If it will cause some problems later, I'l just reduce the map size.

Ok, the point of all thoose special effects. I'm not that good at explaining, but will try.

I'm making a random dungeon generator. Meaning that a random dungeon is created after the map is loaded.
For the dungeon I need something that looks like floors and walls. The best way to acomplish this is to use special effects.

When the map is loaded, it will be filled with special effects that look like normal dirt 128 points above the ground.
When the dungeon is creating a hallway or room, it will replace the 'dirt' effects with 'floor-looking' effects that will be created at the ground,
meaning there will be a 128 point height difference betwen the floor effects and the dirt effects.

As for the walls. For each square that is turned into a floor, I will check the square above and to the right.
If any of thoose squares contains a wall facing the floor square or if they are already made into floor squares, I will do nothing.
If not, I will create a 'wall' ish special effect there and a large vision blocker. That will also prevent units from walking through it.

The code in the previous post shows how I handle all the 'dirt' effects. They can easily be accessed later and checked according to the grid system.
I will create something similar for the walls later.

The result will be a dungeon with walls and floors. The point of all thoose dirt effects that are created in the code earlier is to make it look like you are below the terrain level. There is no other way to do this.

I know this will work. Just don't know much about memory leaks.

EDIT: The giant size and number of effects is just to test how big it can be before causing problems. The playable version will most likely be smaller.

EDIT2: The 'dirt' special effects is visible to the players when a vision blocker is on the same square. I could just create thoose effects around every floor square
because you never see any of the others, but I'l save that for later. Every square on the map can be visible depending on how the dungeon is generated.
An alternative solution could be to lower the terrain by 128 points in every corner of every floor square. That way you would only need 'dirt' effects at every square adjacent to a floor square. But as I said, every square might be made visible :)
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
Sew Blizzard they did not make a perfect game engine.
The test can be shortened to something like:
JASS:
//jass tags: [ jass]  and [ /jass]
local integer i=0
local integer j=0
loop
exitwhen i==#####
  set j=0
  loop
  exitwhen j==#####
  call DestroyEffect(AddSpecialEffect("blah",i,j)
  set j=j+1
  endloop
  set i=i+1
  call TriggerSleepActions(0)
endloop
 

Vex

Vex

Level 3
Joined
Dec 1, 2007
Messages
33
I used the task manager to monitor the ram ussage yes.

I know the test could be done shorter and simpler :p Just didn't know that there would be a leak issue before I finished the first loop.

Also wanted to know if there was some limit and how the game would perform with huge numbers like thoose :)

Some other guy suggested looking into vJass for theese leak issues, so I know enough to move on now.
Thanks for the replies.
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
vJass can't take care of the leaks.
What Herman suggested, was about the question you asked about a number of effects.
He suggested using structs.
And by removing leaks, people mean removing the memory leak as much as possible.
 

Vex

Vex

Level 3
Joined
Dec 1, 2007
Messages
33
I see.

Guess I'l scrap the idea of filling the map with effects then removing/replacing them as the dungeon is generated. Might aswell generate the whole thing with boolean arrays first. Then place the effects after and have them there during the rest of the game.
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
But still, vJass is great.
For instance 2D arrays.
(not that you can't make it without them) ;)
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
I haven't had any problems with them so far :p

P.s.
Are you still waiting for the host?
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Scrape that idea? Finally a smart idea.

As to why it takes so much ram in the first place.

Let's calculate how much ram every effect requires (this is all guesses and probably inaccurate of course).

It has a x float - 4 bytes.
It has a y float - 4 bytes.
It has a model (?) - ? bytes (how big are the effects, 5-20 kb?).
it has a widget targetWidget (not sure about this) - ? bytes.
it has a string attachPointName (not sure about this) - probably something between 5-10 bytes.
And it has all it's methods that take ? bytes.

This doesn't really say a lot, of course, but let's only concentrate on the model variable as it's the only really big thing.

Let's say your effect is very small (I think this is small) and is 5 kb.

You want to create what, 170,000*5 = 850000 kb = 850 mb.

By the way, since you said it took around 750 mb it seems like effects are something between 3.5 and 5 kb (but I may be wrong, it's all guesses).

And, all this is without even considering all the other things that run on your warcraft, and of course warcraft itself.
 
Status
Not open for further replies.
Top