kivy / kivent

KivEnt is an entity-based game engine for Kivy
http://www.kivent.org
573 stars 94 forks source link

Switching between games saturates memory #253

Open IvanDragogear opened 7 years ago

IvanDragogear commented 7 years ago

Hello, I have a menu that allows me to open different mini games, each mini game has its own gameworld with its own systems, the operation seems correct but, when I return to main_menu the memory used by the mini game_1 or mini game_2 is not released, for example:

1.-Open app | main_menu()→4.5%mem 2.-Open game 1 | acces_game_1() → 7.5%mem 3.- Exit() | main_menu() →7.5%mem 4.-Open game 2 | acces_game_2() → 10.6%mem 5.- Exit() | main_menu() →10.6%mem 6.-Open game 2 | acces_game_2() → 13.8%mem 7.- Exit() | main_menu() →13.8%mem 8.-Open game 2 | acces_game_2() → 16.8%mem 9.- MemoryError

game

I think the problem is the saturation of memory, so it tries to eliminate the systems, entities and the gameworld when returning to the main_menu()

self.gameworld.clear_entities() self.gameworld.delete_system('sys_game1') del self.gameworld del self

But it does not work, the memory keeps accumulating until it causes an error, then I ask: How to properly delete a gameworld? How do I clean the game memory?

Here I leave the complete error log: Traceback (most recent call last): File "main.py", line 90, in MainApp().run() File "/usr/local/lib/python2.7/dist-packages/kivy/app.py", line 828, in run runTouchApp() File "/usr/local/lib/python2.7/dist-packages/kivy/base.py", line 504, in runTouchApp EventLoop.window.mainloop() File "/usr/local/lib/python2.7/dist-packages/kivy/core/window/window_pygame.py", line 403, in mainloop self._mainloop() File "/usr/local/lib/python2.7/dist-packages/kivy/core/window/window_pygame.py", line 289, in _mainloop EventLoop.idle() File "/usr/local/lib/python2.7/dist-packages/kivy/base.py", line 339, in idle Clock.tick() File "/usr/local/lib/python2.7/dist-packages/kivy/clock.py", line 581, in tick self._process_events() File "kivy/_clock.pyx", line 367, in kivy._clock.CyClockBase._process_events (kivy/_clock.c:7410) File "kivy/_clock.pyx", line 397, in kivy._clock.CyClockBase._process_events (kivy/_clock.c:7285) File "kivy/_clock.pyx", line 395, in kivy._clock.CyClockBase._process_events (kivy/_clock.c:7207) File "kivy/_clock.pyx", line 167, in kivy._clock.ClockEvent.tick (kivy/_clock.c:3201) File "kivent_core/gameworld.pyx", line 282, in kivent_core.gameworld.GameWorld.init_gameworld.lambda (kivent_core/gameworld.c:5907) File "kivent_core/gameworld.pyx", line 276, in kivent_core.gameworld.GameWorld.init_gameworld (kivent_core/gameworld.c:6033) File "kivent_core/gameworld.pyx", line 225, in kivent_core.gameworld.GameWorld.allocate (kivent_core/gameworld.c:4941) File "kivent_core/memory_handlers/membuffer.pyx", line 103, in kivent_core.memory_handlers.membuffer.Buffer.allocate_memory (kivent_core/memory_handlers/membuffer.c:1254) MemoryError

Kovak commented 7 years ago

Most of the time I would do this by having different states in the same GameWorld, as a GameWorld is kind of expected to be a singleton type class that persists for the life of your application allocating memory once. I think we might need to extend kivent a bit to make it safe to deallocate and reallocate more gameworlds. Keep in mind that just calling del isn't quite enough since this just marks the object for GC and does not guarantee that it has been GC'd at that time. KivEnt should clean itself up upon being GC'd, you might need to memory profile to get an idea of where things are being used.

IvanDragogear commented 7 years ago

Thank you, answer so quickly. Then the best for now, is to join both mini-games on the same gameworld, although the games are of very different mechanics, each with its own menus and states also. T_T One is a "bullet-hell" without gravity and the other is a "beat'n up platforms" with gravity on the y-axis.

Kovak commented 7 years ago

It might be more efficient to investigate what still needs to happen to enable timely GC of an entire GameWorld.

IvanDragogear commented 7 years ago

I'm doing it, when I have the solution I'll put it here as usual, thank you.

Kovak commented 7 years ago

feel free to ask questions as you go, I fear this might be a bit of a hairy issue, but not impossible. Most everything should have triggers to clean itself up memory wise. The ideal case would probably be a function to call that tears down everything and then we can just let the remaining python objects get gc'd as normal

IvanDragogear commented 7 years ago

It seems that I can not use the GC because gameworld does not have del () and 'del gameworld' also does not work for the same reason.