I have a MonoTouch app out in the wild that dies sometimes with mprotect errno 12 (out of memory), and it always seems to get at least one ReceiveMemoryWarning notification beforehand.
I'm wondering what the right way to respond to this is. There are two types of things that my app could free: OpenGL textures and managed memory.
My questions about this are:
OpenGL textures: Will deleting OpenGL textures help?
Managed memory: I can't free this directly, but I can get null out references to it. Is that enough?
GC.Collect: Should I call GC.Collect() at the end of my handler? Does GC.Collect do anything immediately, or does it schedule a collection for the future?
Anything else I can/should do in response to this?
I ran into this a while back in my app using OpenGL. For me, it really was a memory leak.
[DllImport("/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics")]
public static extern void CGDataProviderRelease(IntPtr provider);
and after you call
GL.TexImage2D.....
you need to call CGDataProviderRelease(data.Handle);
now that being said, you might want to look at this:
http://forums.monotouch.net/yaf_postst1541.aspx
Related
I switched to Vulkan from OpenGL to use multi-threading improvements.
In OpenGL, I was able to load dynamically object to the scene (buffer, textures, etc) while rendering by using a waiting system. I was loading all app-side stuffs in a thread, then when it was ready, just before a frame render in the main thread, I was sending everything into the video memory. That was fine.
With Vulkan, I know I can call some functions between threads without provoking the well known segfault from OpenGL. But, this doesn't works with vkQueueSubmit(). I already know, I tried the naive way. To me, it seems logical you can't bother a queue from multiple threads.
I came with some ideas, but I don't know which one is good or bad.
First, I would go the OpenGL way, I will prepare everything I can from the CPU/App side, then just before render a frame, I will submit buffers (with transfer queue) to the video memory. But I feel there is no a real improvement from OpenGL way...
Second, I will try to use the synchronization mechanism to be able to send buffers in a thread and render from an other. But I keep reading there is a lot of way to slow down everything by causing irrelevant locks or by using incorrectly semaphores and fences.
So my question, is basically what path to pick to solve this problem ? How can I load a buffer dynamically from an other thread while the main thread is rendering without making too much pain to performances ? How Vulkan can help ?
If you want to stream resources for immediate use (i.e. the main render cannot proceed without them), then you're pretty much going to either block the main thread waiting, or have it spin doing something visually interesting (e.g. an animated loading screen) waiting for the resources to load.
If you want to stream resources while the app is doing real rendering then the main trick here is to load resources asynchronously in the background and only switch to using those resources in the main thread once they are already loaded. If the main thread ever ends up actually blocked on a semaphore then you've probably already started dropping frames, so your "engine" design needs to ensure that never happens. A lot of game use simple low-detail proxy objects as stand-in versions while the high-detail version is loading in the background.
None of this is particularly related to the graphics API - both GL and Vulkan need the same macro-scale behavior. Vulkan API features don't particularly help because the major bottlenecks which cause problems here are storage/network/CPU which have nothing to do with the graphics part of the problem.
I decided to trust threads !
In the first place it seems to work, I get a lot of :
[MESSAGE:Validation Error: [ UNASSIGNED-Threading-MultipleThreads ] Object 0: handle = 0x56414228bad8, type = VK_OBJECT_TYPE_QUEUE; | MessageID = 0x141cb623 | THREADING ERROR : vkQueueSubmit(): object of type VkQueue is simultaneously used in thread 0x7f6b977fe640 and thread 0x7f6bc2bcb740]
But it works !
So, the basic idea is to have a thread for loading objects while the engine is drawing. This thread takes care of creating the UBO for the location of the object, then when the geometry is loaded from RAM, it creates the VBO and IBO (I left material with image/UBO on hold for now), then creates the graphics pipeline (with layout, descriptor layout, shaders compiled with GLSLang on the fly) (The next idea is to reuse pipeline for similar needs) and finallly sets a flag to say the object is ready to use. In the other hand, I have my main thread rendering and takes new objects when they shows up ready.
I think it works because I have a gentle video card (GTX 1070) with multiple queues setup, I had one for graphics and an other one for transfer setup.
I'm pretty sure, this will crash or goes poorly with a GPU with a single queue, and this should be why the validation layers tolds me these messages.
I am setting a texture on a material with this code. Under Memory tab in Android studio, I noticed that memory increases each time when this code runs. Looks like memory leak or bad memory management to me. How should I set texture repeatedly at runtime to a material so that memory gets managed properly.
Code:
Timer.schedule(new Timer.Task() {
#Override
public void run() {
materials.get(5).set(TextureAttribute.createDiffuse(new Texture("400px/"+mat5+".png")));
}
}, delay2);
The problem is every time the Timer executed the Task, you're creating a new Texture. Textures are Disposable and as such, need to be disposed when not used anymore. In your above code, you aren't keeping a reference to the created Textures so you lose the ability to dispose of them. This creates memory leaks.
One solution to this, is to use an AssetManager instead of managing your assets yourself. This class aims to relieve you of the effort of managing your assets' memory consumption.
Another solution is to keep references to the created Texutres and makeing sure they are properly disposed when not needed.
Personally, I'd go with the first solution. It might be intimidating at first, but once AssetsManager is mastered, it really does a good job when it comes to, well, managing your assets.
I am using the NodeJS VM Module to run untrusted code safely. I have noticed a huge memory leak that takes about 10M of memory on each execution and does not release it. Eventually, my node process ends up using 500M+ of memory. After some digging, I traced the problem to the constant creation of VMs. To test my theory, I commented out the code that creates the VMs. Sure enough, the memory usage dropped dramatically. I then uncommented the code again and placed global.gc() calls strategically around the problem areas and ran node with the--expose-gc flag. This reduced my memory usage dramatically and retained the functionality.
Is there a better way of cleaning up VMs after I am done using it?
My next approach is the cache the vm containing the given unsafe code and reusing it if it I see the unsafe code again (Background:I am letting users write their own parsing function for blocks of text, thus, the unsafe code be executed frequently or executed once and never seen again).
Some reference code.
async.each(items,function(i,cb){
// Initialize context...
var context = vm.createContext(init);
// Execute untrusted code
var captured = vm.runInContext(parse, context);
// This dramatically improves the usage, but isn't
// part of the standard API
// global.gc();
// Return Result via a callback
cb(null,captured);
});
When I see this right this was fixed in v5.9.0, see this PR. It appears that in those cases both node core maintainer nor programmers can do much - that we pretty much have to wait for a upstream fix in v8.
So no, you can't do anything more about it. Catching this bug was good though!
I want to read a byte of memory but don't know if the memory is truly readable or not. You can do it under OS X with the vm_read function and under Windows with ReadProcessMemory or with _try/_catch. Under Linux I believe I can use ptrace, but only if not already being debugged.
FYI the reason I want to do this is I'm writing exception handler program state-dumping code, and it helps the user a lot if the user can see what various memory values are, or for that matter know if they were invalid.
If you don't have to be fast, which is typical in code handling state dump/exception handlers, then you can put your own signal handler in place before the access attempt, and restore it after. Incredibly painful and slow, but it is done.
Another approach is to parse the contents of /dev/proc//maps to build a map of the memory once, then on each access decide whether the address in inside the process or not.
If it were me, I'd try to find something that already does this and re-implement or copy the code directly if licence met my needs. It's painful to write from scratch, and nice to have something that can give support traces with symbol resolution.
I am almost finished with my first monotouch app, almost that is, but for some big problems with memory leaks. Even though I override the viewDidUnload on every view controller so that for every UI element that I create I first remove it from its superview, then call Dispose and then set it to null, the problem persists. Using Instruments is no help, it doesn't detect the memory leaks and the memory allocations doesn't point me to anything that I can track.
My app uses mainly the MPMoviePlayer to play video streams and also displays an image gallery from images loaded through http. Both operation are causing problems.
Any ideas would be very much appreciated, thanks.
The Master is right of course. Gracias Miguel. I wanted though to give a more thorough explanation of what I did, with the hope that it may help future Xamarin colleges.
1) The MPMoviePlayer stores a video buffer which is kind of sticky. What I have done is have a unique instance running on the AppDelegate an reuse this across the views that show a video. So instead of initializing the MPMoviePlayerController with an url you use the constructor with no arguments, and then set the ContentUrl property and call Play().
2) Do not rely on ViewDidUnload being called to clean up you objects, because it is not called consistently. For example I use a lot of modal view controllers and this method never got called. Memory just kept accumulating until the app crashed. Better call you clean up code directly.
3) Images were the biggest memory hug I had. Even Images inside UIImageViews that were just used as background would never get disposed. I had to specifically call the following code on each image before I could clear up the memory:
myImageView.RemoveFromSuperview();
myImageView.Image.Dispose();
myImageView.Image = null;
myImageView.Dispose();
myImageView = null;
4) Beware of the UIWebView, it can hug a lot of memory, specially if there is some kind of AJAX interaction running on the page that you are loading. Calling the following code help a little but didn't solve all the problems. Some memory leaks remain that I wasn't able to get rid off:
NSString keyStr = new NSString("WebKitCacheModelPreferenceKey");
NSUserDefaults.StandardUserDefaults.SetValueForKey(NSObject.FromObject(val), keyStr);
5) If you can, avoid using Interface Builder. On several occasions I was never able to release UI elements created on the xib files. Positioning everything by hand can be a pain but if you are using a memory intensive application creating all your view controllers in code may be the way to go.
6) Using anonymous methods as event handlers is nice and my help code readability, but on some occasions not being able to manually detach an event handler became a problem. References to unwanted object remain in memory.
7) In my UITableViewSource I was able to have a more efficient memory handling by creating the UIImages that I use to style the cells independently and then just reusing them on my GetViewForHeader and GetCell methods.
One last thing; even though instruments is not really compatible with the way monotouch is doing things using the "Memory Monitor" was a valuable tool, if you are having problem it can indeed help.
These strategies solved most of my problems. Some may be pretty obvious in hindsight but I thought it wont hurt to pass them along.
Happy Coding and long live c# on the iPhone
The UI elements are not likely the responsible ones, those barely use any memory. And calling Dispose()/nulling helps, but only a tiny bit.
The more likely source of the problem are objects like the MPMoviePlayer, the image downloading and the image rendering. You might be keeping references to those objects which prevent the GC from getting rid of them.