MobiVM / robovm

Ahead of time compiler for JVM bytecode targetting iOS, Mac OSX and Linux
https://mobivm.github.io
967 stars 133 forks source link

Heap Size #662

Closed cacophany53 closed 2 years ago

cacophany53 commented 2 years ago

How does RoboVM determine the heap size of its JVM on IOS? Currently running into crashes on iPad with 3GB of ram, and I suspect memory usage is to blame. I would like to know if RoboVM limits its max heap size to the maximum allowed RAM granted to an app by default, or if there's something I need to do to configure a specific heap size.

dkimitsa commented 2 years ago

hi, default configuration -- heap size is not limited and will grow once required (and till there are memory that can be obtained from system). you can add 'robovm.ini' file to resources and manipulate heap size by mx parameter there. but I would start looking into crash log to see exact reason of the crash

cacophany53 commented 2 years ago

Thanks. I added mx=1014M to Robovm.ini under the resources folder of the eclipse project.

I profiled the app using the Xcode allocations instrument utility and found that there appeared to be a memory leak. It appears each MTLTexture object created correlates to an allocation of an object in the VM IOAccelerator category, with the following stack:

IOGPUResourceCreate 
-[IOGPUMetalResource initWithDevice:options:args:argsSize:] 
-[IOGPUMetalTexture initWithDevice:descriptor:sysMemSize:sysMemRowBytes:vidMemSize:vidMemRowBytes:args:argsSize:]   
0x1f0fc9d48 
-[MTKTextureUploader newTextureWithData:options:]   
__71-[MTKTextureLoader _loadData:options:uploader:label:completionHandler:]_block_invoke_2  
_dispatch_call_block_and_release    
_dispatch_client_callout    
_dispatch_continuation_pop  
_dispatch_async_redirect_invoke 
_dispatch_root_queue_drain  
_dispatch_worker_thread2    
_pthread_wqthread   
start_wqthread  

My App uses the following code to delete textures (MTLTexture) no longer in use:

texture.setPurgeableState(MTLPurgeableState.Empty);
texture.dispose();
texture = null;

Unfortunately, the number of IOAccelerator object allocations never decreased over time as expected, even when the above code was called, but only increased as new textures were allocated.

Is this the correct way to remove allocations of an MTLTexture? Do I need to force garbage collection to occur in order for these to be cleaned up?

dkimitsa commented 2 years ago
texture.dispose();
texture = null;

is a way to force releasing native ObjC part of Java object. it doesn't delete object but reduce retainCount. if object is retained somewhere else in native side it will not be released. you can check retainCount() before calling dispose. if MTLTexture is retained somewhere as well -- you can check with instrumentation where it get retained/released to find a place where it might be retained so it is not deallocated.

cacophany53 commented 2 years ago

Thanks for the info. Just before I call dispose, it's returning 2 for retainCount. Note that all the code execution is within autoreleasepool blocks. Is a retainCount of 2 expected in this case? Or does this suggest that something else is holding onto it?

When I look at the persistent allocation in the instrumentation, the retain count is blank for those instances of VM IOAccelerator.

cacophany53 commented 2 years ago

It appears I've found a possible solution.

Adding a call to release() on MTLTexture seems to fix the leak.

dkimitsa commented 2 years ago

actually release() its a compensation for a bug -- it should be working without it. if you provide minimal code snippet to reproduce -- I will look into root case. thx