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.
Related
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 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.
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
Summary
I have written a process monitor command-line application that takes as parameters:
The process name or process ID
A CPU Threshold percent.
What the program does, is watches all processes with the passed name or pid, and if their CPU usage gets over the threshold%, it kills them.
I have two classes:
ProcessMonitor and ProcessMonitorList
The former, wraps around System.Diagnostics.PerformanceCounter
The latter is an IEnumarable that allows a list-like structure of the former.
The problem
The program itself works fine, however if I watch the Memory Usage on Task Manager, it grows in increments of about 20kB per second. Note: the program polls the CPU counter through PerformanceCounter every second.
This program needs to be running on a heavily used server, and there are a great number of processes it is watching. (20-30).
Investigation So far
I have used PerfMon to monitor the Private Bytes of the process versus the Total number of Bytes in all Heaps and according to the logic presented in the article referenced below, my results indicate that while fluctuating, the value remains bounded within an acceptable range, and hence there is no memory leak:
Article
I have also used FxCop to analyze my code, and it did not come up with anything relevant.
The Plot Thickens
Not being comfortable with just saying, Oh then there's no memory leak, I investigated further, and found (through debugging) that the following lines of code demonstrate where the leak is occurring, with the arrow showing the exact line.
_pc = new PerformanceCounter("Process", "% Processor Time", processName);
The above is where _pc is initiated, and is in the constructor of my ProcessMonitor class.
The below is the method that is causing the memory leak. This method is being called every second from my main.
public float NextValue()
{
if (HasExited()) return PROCESS_ENDED;
if (_pc != null)
{
_lastSample = _pc.NextValue(); //<-----------------------
return _lastSample;
}
else return -1;
}
This indicates to me that the leak exists inside the NextValue() method, which is inside the System.Diagnostics.PerformanceCounter class.
My Questions:
Is this a known problem, and how do I get around it?
Is my assumption that the task manager's memory usage increasing implies that there is indeed a memory leak correct?
Are there any better ways to monitor multiple instances of a specific process and shut them down if they go over a specific threshold CPU usage, and then send an email?
So I think I figured it out.
Using the Reflector tool, I was able to examine the code inside System.Diagnostics.
It appears that the NextValue method calls
GC.SuppressFinalization();
This means that (I think, and please correct if I am wrong) that I needed to explicitly call Dispose() on all my classes.
So, what I did is implement IDisposable on all of my classes, especially the one that wrapped around PerformanceCounter.
I wrote more explicit cleanup of my IList<PerformanceMonitor>, and the internals,
and voilĂ , the memory behavior changed.
It oscillates, but the memory usage is clearly bounded between an acceptable range over a long period of time.
A lot of Java ME tutorials use the startApp() method for creating and initializing objects and the constructor is left blank. However, the startApp() method is also invoked when the MIDlet resumes from a paused state. This causes all the objects to be re-initialized and any changes made are lost.
I have also noticed that the netbeans IDE, in its auto-generated code, uses many if(object==null) statements in startApp() to check if the object was created earlier.
Would it not make sense to simply do all the object creation and initialization in the constructor itself? Is there any reason for not doing this?
This is in part about understanding the MIDP threading model.
What thread the MIDlet constructor is called in depends on who developed the Java Virtual Machine on the phone.
Developers have a tendency to rely only on what the MIDP specification says in that area, which is how startApp, pauseApp and lcdui event handling should behave.
However there are only a few cases where this is important.
The second aspect to this issue is software developers trying to free as much resources (memory, file handles, sockets...) as possible when the MIDlet is paused.
Again, there are cases when MIDlets should hang on to some resources even when paused but you really need to think about what you're doing (and understand it better than casually) when coding that kind of behavior.
It is also worth remembering that some phones always keep the JVM process running. When they also have a JVM that doesn't support class unloading (as is usual in a J2ME world), this means that static variables can remain in memory even after the MIDlet has been completely destroyed.