Skip to content
This repository has been archived by the owner on Jan 4, 2022. It is now read-only.

Fix OOM error #4

Open
uyjulian opened this issue Sep 22, 2019 · 11 comments
Open

Fix OOM error #4

uyjulian opened this issue Sep 22, 2019 · 11 comments

Comments

@uyjulian
Copy link
Owner

Out of memory error occurs, preventing large assets from being loaded and "The Question" from being run in album override.

@uyjulian
Copy link
Owner Author

OOM error can still occur, but data aborts are no longer thrown.

@baconwaifu
Copy link

Applet mode RAM restrictions are well known, and impossible to bypass without a patch in atmosphere or other CFW. The best you can do is make it throw a "this won't work, launch in game mode" error instead of crashing.

@uyjulian
Copy link
Owner Author

uyjulian commented Nov 19, 2019

OOM in "The Question" did not occur before I made an update to libnx.

Even if not using album override, the application can still run out of memory when large assets are loaded over a period of time.

@baconwaifu
Copy link

sounds like a memory leak then. Given that python is garbage-collected, a core dump should be able to piece together what filled the RAM. I'll take a look with twili when I have the time.

@uyjulian
Copy link
Owner Author

The following warning appears in the log:

romfs:/Contents/renpy/display/pgrender.py:118: UserWarning: Memory leak via Surface in pygame_sdl2.
  surf = Surface((width + 4, height + 4), 0, sample)

A couple of OOM tracebacks:

...
  File "romfs:/Contents/renpy/display/core.py", line 2314, in event_peek
    self.check_background_screenshot()
  File "romfs:/Contents/renpy/display/core.py", line 2162, in check_background_screenshot
    self.bgscreenshot_surface = renpy.display.draw.screenshot(self.surftree, self.fullscreen_video)
  File "gldraw.pyx", line 1382, in renpy.gl.gldraw.GLDraw.screenshot
  File "romfs:/Contents/renpy/display/pgrender.py", line 118, in surface
    surf = Surface((width + 4, height + 4), 0, sample)
  File "src/pygame_sdl2/surface.pyx", line 164, in pygame_sdl2.surface.Surface.__init__
error: Out of memory
...
  File "render.pyx", line 166, in renpy.display.render.render
  File "render.pyx", line 259, in renpy.display.render.render
  File "romfs:/Contents/renpy/text/text.py", line 2008, in render
    layout = Layout(self, width, height, renders, splits_from=virtual_layout)
  File "romfs:/Contents/renpy/text/text.py", line 821, in __init__
    tex = renpy.display.draw.load_texture(surf)
  File "gldraw.pyx", line 747, in renpy.gl.gldraw.GLDraw.load_texture
  File "gltexture.pyx", line 883, in renpy.gl.gltexture.texture_grid_from_surface
  File "gltexture.pyx", line 319, in renpy.gl.gltexture.TextureCore.load_surface
  File "gltexture.pyx", line 1174, in renpy.gl.gltexture.premultiply
MemoryError
...
    if self.event_peek():
  File "romfs:/Contents/renpy/display/core.py", line 2314, in event_peek
    self.check_background_screenshot()
  File "romfs:/Contents/renpy/display/core.py", line 2162, in check_background_screenshot
    self.bgscreenshot_surface = renpy.display.draw.screenshot(self.surftree, self.fullscreen_video)
  File "gldraw.pyx", line 1382, in renpy.gl.gldraw.GLDraw.screenshot
  File "romfs:/Contents/renpy/display/pgrender.py", line 118, in surface
    surf = Surface((width + 4, height + 4), 0, sample)
  File "src/pygame_sdl2/surface.pyx", line 164, in pygame_sdl2.surface.Surface.__init__
error: Out of memory

The following could be possible:

  1. Memory leak in renpy.display.pgrender.Surface
  2. Memory allocation/deallocation in threads is not working correctly

@uyjulian
Copy link
Owner Author

On Linux, I used a test project with various large images, audio, and music, and looped it for five minutes. Memory usage started at 529688 (title screen, before start) then ended at 1906304 (title screen, after start).
That is not even close to hitting the Switch's memory amount of 4GB.

It may be possible to get the amount of available memory by using

size_t mem_available;
svcGetInfo(&mem_available, InfoType_TotalMemorySize, CUR_PROCESS_HANDLE, 0);

,

size_t mem_used;
svcGetInfo(&mem_used, InfoType_UsedMemorySize, CUR_PROCESS_HANDLE, 0);

,

struct mallinfo mi = mallinfo();
size_t heap_available = mi.uordblks;

and

struct mallinfo mi = mallinfo();
size_t heap_used = mi.fordblks;

, but I haven't tried it out yet.

I may just do the following:

  1. Decreasing heap size using __nx_heap_size variable
  2. Allocating memory to the Python object allocator using svcMapPhysicalMemory and virtmemReserve

Python object allocator obmalloc.c uses mmap to decrease heap fragmentation.

@uyjulian
Copy link
Owner Author

For some reason, the heap size is randomized... Check out https://gist.github.com/uyjulian/df5e5c44a8304ba17536609f0358ac0a for how I determined this

@uyjulian
Copy link
Owner Author

uyjulian commented Nov 1, 2020

I may try to use virtmemFindAslr / virtmemAddReservation / virtmemRemoveReservation to assist in heap fragmentation…

@uyjulian
Copy link
Owner Author

Need more confirmation that virtmemFindAslr will fix the issue…

@uyjulian
Copy link
Owner Author

Nope… In fact, virtmemFindAslr has a worse issue.

@uyjulian
Copy link
Owner Author

It looks like heap is limited to 384 MiB, so there's not much I can do right now until PhysicalMemory SVCs are implemented…

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants