Freeing Memory?
BlitzMax Forums/BlitzMax Programming/Freeing Memory?
| ||
I'm looking into a couple of memory issues with my application and I was wondering about GCMemAlloced(). It seems that when GCMemAlloced() is reporting 1,500,000 bytes of memory that my application is very slow. I know I have some memory clean-up issues; but 1,500,000 bytes does seem like enough to cause any issues? Any insite? |
| ||
Wow, I really had a misconception about how the BlitzMax memory management work. Have a look at he following:Print "Allocated Memory before call to m_pTGamePlayScreen.Initialize() = " + GCMemAlloced() m_pTGamePlayScreen = New TGamePlayScreen m_pTGamePlayScreen.Initialize() Print "Allocated Memory after call to m_pTGamePlayScreen.Initialize() = " + GCMemAlloced() m_pTGamePlayScreen = Null m_pTGamePlayScreen = New TGamePlayScreen m_pTGamePlayScreen.Initialize() Print "Allocated Memory after 2nd call to m_pTGamePlayScreen.Initialize() = " +GCMemAlloced() GCCollect() Print "Allocated Memory after call to GCCollect() = " +GCMemAlloced() And here is the output: Allocated Memory before call to m_pTGamePlayScreen.Initialize() = 77149 TGamePlayScreen.Initialize Allocated Memory after call to m_pTGamePlayScreen.Initialize() = 156311 TGamePlayScreen.Initialize Allocated Memory after 2nd call to m_pTGamePlayScreen.Initialize() = 232279 Allocated Memory after call to GCCollect() = 229361 I would have though thay setting m_pTGamePlayScreen = Null would have freed the memory? |
| ||
Doesnt whether the memory gets freed depend on what the type is. For example if your type is a pointer to a memory area you have set asside. Then Null dosent free the memory. I asked a similar question a couple of days ago and was informed that the Gcollection messes up when its deletes Tlists as well (I have never seen this but was told its true) Post the type |
| ||
I would have though thay setting m_pTGamePlayScreen = Null would have freed the memory? It does, I think, but only the next time GC is run. In the following case GC is run at x=42 (for me)... Type ttest End Type Graphics 640,480 For x = 0 To 50 Cls mynew:ttest = New ttest DrawText GCMemAlloced(),0,0 mynew = Null DrawText GCMemAlloced(),0,20 DrawText x,0,40 Flip WaitKey() Next |
| ||
m_pTGamePlayScreen = New TGamePlayScreen If of type TGamePlayScreen which is a type. Inside the Initialization of TGamePlayScreen a lot of different types are initialized: Field m_pTTileMapLayer1:LayeredTileMap = Null Field m_pTTileMapLayer2:LayeredTileMap = Null Field m_pTTileMapLayer3:LayeredTileMap = Null Field m_fLevelCompleteFadePercentage:Float Field m_iState:Int Field m_fLayer1Alpha:Float = .5 Field m_fLayer2Alpha:Float = 0.55 '.4 Field m_fLayer3Alpha:Float = 0.45 '.3 Field m_iBlend1:Int = 3 Field m_iBlend2:Int = 4 Field m_iBlend3:Int = 4 Field m_iDebug:Int = False Field m_iLevel:Int = -1 Field m_pTStarship:TStarship = Null Field m_pTPlayerList:TList = Null Field m_pTGalaxy:TGalaxy = Null Field m_pTPlayersAvatar:TStarship = Null Field m_pTWeaponsMenu:TWeaponsMenu = Null And they are initialized further in the lower objects. If setting a new'ed object to null doesn't work, how do you free it? I can free all the lower objects first, but I would be setting them to null to free them? |
| ||
I would say (Going only on what Ive been told), is that the M-PtPlayerlist:Tlist might be the problem. Probably someone who know better should advice you, but the advise given to me was to implicetly free the links in a tlist. http://www.blitzmax.com/Community/posts.php?topic=59935 |
| ||
When you set your TGamePlayScreen to null and remove it from a list (if it's on one) and/or it falls out of scope then the pointer to, for example, m_pTGalaxy:TGalaxy will be deleted. If this is the only reference to that TGalaxy object it will be removed when GC next runs. However, if it is on a list and you don't remove it from that list you'll still have a reference to it. You'll need to remove it from the list when you delete the object which references it. Global alllist=CreateList() Type ttest Field t1:ttest1 End Type Type ttest1 End Type Graphics 640,480 For x = 0 To 5000 Cls mynew:ttest = New ttest mynew.t1:ttest1=New ttest1 ListAddLast alllist,mynew.t1 DrawText GCMemAlloced(),0,0 ' ListRemove alllist,mynew.t1 mynew = Null DrawText GCMemAlloced(),0,20 DrawText x,0,40 Flip Next |
| ||
Tony, m_pTGamePlayScreen is a field of the TReferee object. TReferee exists throughout the life of the game. it is not going to fall out of scope? Thanks |
| ||
Is there anyway to see everything that is still being allocated. Not the total memory, but the types of objects? Any external programs that do this? |
| ||
m_pTGamePlayScreen is a field of the TReferee object. TReferee exists throughout the life of the game. it is not going to fall out of scope? OK, so the TReferee object's m-pTGamePlayScreen field (which you have set to null) will no longer reference the TGamePlayScreen object. If the TGamePlayScreen object is not on a list and nothing else references it, the memory it used will be freed next (or returned to the 'pot') next time GC is run. As far as I know there is nothing that can list existing objects. Global alllist=CreateList() Type treferee Field t2:ttest End Type Type ttest Field t1:ttest1 End Type Type ttest1 End Type Graphics 640,480 For x = 0 To 5000 Cls mynew:treferee = New treferee mynew.t2:ttest = New ttest mynew.t2.t1:ttest1=New ttest1 ListAddLast alllist,mynew.t2.t1 DrawText GCMemAlloced(),0,0 ' ListRemove alllist,mynew.t1 mynew.t2 = Null DrawText GCMemAlloced(),0,20 DrawText x,0,40 Flip Next I might be missing something here but you keep adding to the question. It might be best to post the smallest example which shows the problem. |
| ||
Interesting, I added a bunch of de-allocation code and it help the performance when you start a game over and over. In fact I was able to get the memory reported by GCMemAlloced() up to 3,900,000 bytes without any noticeable performance loss. However, the memory reported by GCMemAlloced() is still increasing. That kind of makes me think that somehow memory can be lost by GCMemAlloced()? Anything below you can see that I overlooked: 'Destory the Game Play View Screen Method Destroy() Local pTPlayer:TPlayer = Null Print "TGamePlayScreen.Destroy" SetImageFont Null 'Null the Player's Avatar m_pTPlayersAvatar.Destroy() m_pTPlayersAvatar = Null 'Null the Tile Maps. m_pTTileMapLayer1 = Null m_pTTileMapLayer2 = Null m_pTTileMapLayer3 = Null 'TODO - Need to Implement Destroy for the Tile Maps. 'Destroy the Player's Avatar. m_pTStarship.Destroy() m_pTStarship = Null 'Remove the Players from the List. For pTPlayer = EachIn m_pTPlayerList 'Destory the Players. m_pTPlayerList.Remove(pTPlayer) pTPlayer.Destroy() pTPlayer = Null Next 'Null the Players List. m_pTPlayerList.Clear() m_pTPlayerList = Null 'Null the Galaxy. m_pTGalaxy.Destroy() m_pTGalaxy = Null 'Null the Weapons Menu. If m_pTWeaponsMenu <> Null m_pTWeaponsMenu.Destroy() m_pTWeaponsMenu = Null End If End Method Also, does calling GCCollect() in automatic mode do anything? Thanks |
| ||
Now I really think I have missed something. Is this taken from some commonly available code? If not, then it will be really difficult to find anything wrong with a single method without the rest of the program. If it's a huge program then you might want to think about writing a debugger module or adding more debug statement. GCCollect will prompt GC to run even in automatic mode... Global alllist=CreateList() Type treferee Field t2:ttest End Type Type ttest Field t1:ttest1 End Type Type ttest1 End Type Graphics 640,480 For x = 0 To 5000 Cls mynew:treferee = New treferee mynew.t2:ttest = New ttest mynew.t2.t1:ttest1=New ttest1 ListAddLast alllist,mynew.t2.t1 DrawText GCMemAlloced(),0,0 ListRemove alllist,mynew.t2.t1 mynew.t2 = Null DrawText GCMemAlloced(),0,20 DrawText x,0,40 GCCollect() Flip Next |
| ||
Are you freeing the tilemaps? (Again this comes down to how you have structured them) If they point to each other (Internsly or externaly) them even tho the mian object goes out of scope, the internal refrences would stop the reference pointer from zeroing. But Im with Tonyg on this, try to make the smalest code possible that still has the problem. |