NSXMLParser iPhone memory strategy for large xml - iphone

I build a parsing algorithm using NSXMLParser.
Im having doubt as to what is the best strategy for keeping my memory usage on a minimum.
I have a valueObject (e.g. "Person") this object has ≈ 30 NSString properties, while parsing the xml I continually alloc and release a temporary Person object as the nodes are traversed.
I checked this and there is only one of these Person objects instantiated at any time.
When a node is traversed and a Person is "build" I pass the Person to a NSMutableArray and release this Person. Seems no problem there. (I'll need the array for a tableView).
When I reach around 50+ Person objects in the array my app just quits, didReceiveMemoryWarning doesn't get called, no other warnings, no parseErrorOccurred, nothing?
If I limit the number of Persons in xml the app does just fine, I haven't been able to find any memory leaks with Instruments.
I think that I simply can't hold 50+ Person objects in an array… seems a bit harsh, but I haven't got much memory experience with the iPhone, so this is just a guess.
The xml is search results from which the user probably only needs a few, so persisting them to my core model to keep them around for display seems a bit crazy.
What would be a good strategy for keeping these Person objects around? or am I missing a huge memory leak since the iPhone should be able to handle much more than this?
Hope some experienced developers can point me in the right direction:)
Thank you!

Despite NSXMLParser being a SAX-based parser it does not support parsing an input stream, which means that the entire XML string you are parsing is kept in memory. This on its own is a big issue, but as you parse the problem gets worse as you start duplicating the string data from the XML in your Person objects.
If your strings are really big, you've got the second problem of having too many parsed Person objects in memory at one time.
The first problem can be solved by using AQXMLParser from Jim Dovey's AQToolkit library, which provides an NSXMLParser-like API but with support for streaming the data from disk.
The second problem can be solved using a disk-based persistence technology, like Core Data, SQLite Persistent Objects, or even just storing the Person objects on disk yourself.

How long are those strings? Generally, on the iPhone 3G and older models, your app should have a minimum of about 20 MB of memory available (much more on the 3Gs). This is no absolute rule, of course, but a decent rule of thumb. To occupy this much memory with 50 objects would mean ~400-500 KB per Person object. Is this in the ballpark? If so, you will probably need a memory management strategy that does not keep all objects in memory at the same time. Core Data can probably help you a great deal in that case.

If you did not receive a memory warning it is probably not the reason your app is quitting. In Xcode go to the organizer, and select the device, then click on the console tab. If they app was shutdown for memory reasons there will be a system message in the console log saying it is killing the app due to memory pressure.

The answer is to chop up the incoming stream, I wrote a post about it some time ago:
https://lukassen.wordpress.com/2010/01/15/feeding-nsxmlparser-a-stream-of-xml/

Related

Memory increase with no release memory

I search how find my problem.
In my application for iPad when i treat data i have an increase memory and never release that memory, i try instruments leaks memory but that not find memory leaks (i try with profile and analyze).
So my question is they have an other instrument for find memory leaks or other methods?
Thanks in advance for your consideration.
P.S : I don't post code cause that concerned a big part of my code but the part where memory increase is a part where i download from a FTP some zip files (based on SimpleFTPSample from Apple Doc) i unzip this files (with framework minizip) this zip files contains some images and XML files i parse this XML files (around 7200 XML files and 35 000 images files saved) i saved some information (issue of parsing) in data base and that its. If you need part of my code for help me ask me.
Make sure if you have Zombies turned off in Scheme:Diagnostics. With Zombies on no memory is ever deleted. Testing for memory leakage should always be done with Zombies off.
This usually happens when you keep the objects in a datastructure (NSDictionary, NSArray, eg), even after you don't need them anymore. Check with Instruments' Allocations which objects are accumulated, and check in your code where you keep instances of those objects.
Another cause could be long-running threads.
If the loading and parsing you mentioned are done in a single thread that takes a long time, then you may need to do #autoreleasepool in a loop somewhere to force temporary objects to be cleaned up regularly.
It might also be no problem at all. You say you load a lot of images. Images are by default cached by iOS, and only released when necessary to clean up memory. If Instruments "Trace Highlights" shows a lot of memory usage, but "Allocations" doesn't, then this is likely the cause.

Does CoreData automatically implement memory warnings?

CoreData, among other things, is designed to keep an application memory footprint low.
However I could not find any information on weather or not it implements the didReceiveMemoryWarning notification.
I assume it drops its cache as this would be the sensible thing to do?
Core Data does something conceptually similar called faulting which limits how many object in the graph are in memory at any given time. I'd read up on it here https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdFaultingUniquing.html

Instruments logging extra living objects

In the initialization of my app, I am reading some data out of a Core Data managed object context. For some reason, even though the executeFetchRequest line of code is called only once, I am seeing 5 living entries in the Instruments Allocations tool object listing. For example, if I drill down into the source code from within Instruments, I see this:
I set a breakpoint on this line, and verified that the app is stopping on this line only once. However, this is what I see as a result in Instruments:
If I look at the stack trace for each of these 5 objects, it is exactly the same, all pointing back to line 135 as shown in the first screen shot. (As you can see, I have tried a few different scenarios and all of them have the same result.)
So I have two questions here.
Question #1: Why do I see 5 living objects?
Question #2: Why are the objects living any way? From what I can tell, everything is being released correctly, and wrapped inside autorelease pools that should take care of these objects.
I am on Xcode 4.2 with the iOS SDK 5.0. Any ideas would be appreciated. Thanks.
The CFData instances are just chunks of data. Perhaps they represent records in the database, but not knowing the internals of CoreData, that's just speculation. They could represent cached data held by the managedObjectContext, but that too is mere speculation.
If you're not seeing any leaks reported, I would not worry too much about it.
Although if anyone has more insight into this, please chime in.

iphone memory issue

I have an iPhone application that will save number of images in it.
I used SQLite in-order to save the images into the application.
There were lot of memory issues after i saved more than 20 images.
Do any one know how many images users can save in their app database?.
if it depends on iphone memory, how can we get that max limit?.
One more thing:
I have removed the database and used the file system to store the images into application.
but same problem replicated.
Can any one suggest me on this.
I owe a lot for your great help.
Thanks in advance.
I believe storing the image in the file system is a much better idea, could you provide us with more information, like image size, and also some of your saving code?
When you say 'memory issue', do you mean leaks causing out of memory exceptions or are you sure your database has filled the device's disk completely. To know how much SQLite can store read the discussion on this question.
On the other hand, if you are having out of memory exceptions (didReceiveMemoryWarning) you need to tune your code. Specially, when working with many images, just avoiding the use of 'imageNamed' factory method does the job. This is because it creates an autorelease object which remains longer in the memory. Instead create UIImages using the 'initWithContentsOfFile' to create the image and release it immediately after it is used. If you still face the memory issue, you probably have some leaks and need to post some code for people to answer more correctly.

Memory leak when application loads in iPhone

I have a navigation based template, when I run my application using Instruments, the very first memory leak comes under:
Leak Object: Malloc 128 bytes
Responsible Library: CoreGraphics
Responsible Frame: open_handle_to_dylib_path
I don't know where this leak is coming from and how remove this.
If it's a default leak, then I think I don't need to worry about it. But if it's not then I have to find a way to remove the leak.
Expanding on deanWombourne perfectly correct answer a bit..
The Leaks Instrument shows you memory that isn't going to be free'd in the normal course of the app (because there aren't any references to it). This in itself is no biggie, it will be free'd when the app exits. A lot of the framework code will allocate and leave these very small chunks of memory allocated. I have no idea if they are mistakes or essential to how the app runs. Whatever, we must accept that they are completely normal.
Leaks will identify these chunks of memory as 'Leaks' and that sounds bad, but this is not really the 'Leaks' that the instrument is there to help you identify.
The 'real' leaks are in the code that can be run many times and which allocate some memory that is never freed, so over time will consume more and more memory until all memory is used and your app will crash.
So if you have an app that no matter how long you use it for or no matter how you use it, it 'leaks' 128 bytes in an apple framework you generally don't have to worry.
However, if you have an app that say, every time you click a button it allocates a new string which is never released - no matter how many bytes the string is - if the user pressed the button enough times this would consume all the memory available to app and eventually crash it. This is the kind of leak you need to watch out for.
The leaks instrument realistically can't tell the difference between the two kinds, but you need to be able to. You might want a kind of singleton object, for example, that there is only ever one instance of, and that needs to exist for the entire lifetime of your app. You create the object on app startup and realistically you never need to free this object, it can be killed when the app exits. Leaks will flag it as a leak, and some other developers that you work with who assume that this means you don't know what you are doing will run to your boss like a little child and say "He's writing really leaky code, and that's reeeeally bad". And your boss, who isn't a programmer will take him seriously because it does sound bad and anyway he scraped a 2.2 in CS from a reputable University so he must know what he's talking about. When really it is completely reasonable and exactly what you meant to do.
So, use the Leaks instrument to find bugs in your code that will ruin your app. Don't worry about every byte found 'Leaking' in an Apple framework.
If it's a one off 128 byte leak then don't worry about it at all, there are better ways to spend your time than thinking about this :)