Store and loading large plists - objective-c

I am parsing some xml and storing the result in a plist save it to file. I later frequently use that plist to search, add/remove stuff and then save it back.
Now, I don't have any problem with this, everything works fine, im just wondering if there's a better/more efficient/faster way of doing this?
About the plist: array of 200 dictionaries with 150 entries each. Some of those entries are array themselves with sub dictionaries of 50-100 entries... (you get the point)
Thanks.

Unless you are running into performance problems I would suggest not worrying about it and just focus on getting the rest of app completed. Premature optimization is the root of all evil (someone had to say it right?).
If you decide that the time has come to make that part of your app as efficient as possible then we would need to see that actual code that you are using to determine if there are more efficient ways to do it. Considering your description of the plist I would guess that if there was anything incredibly inefficient with your strategy and/or implementation then you would already be running up against it with respect to performance.

Related

Saving Data - Core Data vs plist file

I'm writing an iOS applications that saves Music albums(just an exercise I'm doing for the fun of it) .
For every Album there's a singer, song names, time, and a picture
The final result will be a lot of objects with a lot of details including a picture attached to every object. Should I even consider doing something like that with plist? (can pictures be stored in a plist?)
What's the best way to save and access that data?
I'm new to iOS and from the training videos I've seen Core Data is not recommend for the beginner user. Is that really the case?
If I'm going with plist, should I create one plist for every genre for example rap.plist , rock.plist etc' or just a big data.plist?
Thanks
I would go for core data. If you choose the right template when you create your new project in xcode then reduce the once-off overhead work significantly.
With that simple structure I would say that the templates provides nearly everything you need. Just define your model and layout and off you go.
There is just the images where I would spend a bit more time in thinking it over. I personally never put the image data into core data itself. I rather stored them as file and within my core data model I just stored the path and filename to access it. As file name I simply used a timestamp. You could use some auto-increment or other unique id technique but a time stamp would do as well. It will not be visible to the user anyway.
I think the best way you can do this, since you are new to IOS is by using sqlite. Save all the information you want in your local database and display it on the screen.
You can use plist if you have data structure that is small.
Note that property lists should be used for data that consists primarily
of strings and numbers. They are very inefficient when used with large blocks
of binary data. A property list is probably the easiest to maintain, but it will be loaded into memory all at once. This could eat up a lot of the device's memory.
With Sqlite you will easily be able delete , edit, insert your data into the database.
Core data also uses sqlite for data storage only it helps you to manage your data objects, their relationships and dependencies with minimal code.
And since your are new getting started with core data would not be such a good idea i think.. so i would suggest start off with normal sqlite. Save the data in one of your folders of your app and store their path in the database.
You dont have to write different plists.. You can use the same one if you are using.
EDIT : here is a link that will help you with learning sqlite
http://www.iosdevelopment.be/sqlite-tutorial/
you need some more code to set up the core data stack (the store coordinator, the store, the object model, and a context)
it is a tad more complicated but that shouldnt scare you off.
Reading a plist is indeed dead easy but while good for smaller data (like the info.plist) it doesnt scale and soon you need a fullblown DB
As you edited your original question an decided to go with plist now.
In that case I would go for one plist per ablum and one overall plist for the list of albums.
You could, of course, use more plists for categories etc.
However, if you are thinking of data structures like categories you are far better off with core data. Especially when it comes to searching.
No one seems to be mentioning SQLLite, I would go that way and for reasons that I explain here ( https://stackoverflow.com/a/12619813/1104563 ). Hope this helps!
coredata is a apple provided persistant tool, while plist is XML file. The reason why core data is not recommended for beginner, I think, is core data is more difficult than plist from programming perspective. For your application, obviously core data is more suitable. But alternatively, you may also use archive file, that's between core data and plist.

ObjC: Write to .plist, optimized way?

Reading this article for instance, writing an NSDictionary to a plist looks pretty easy. Now, if I just want to modify one single row of an existing plist: Is there any way to update the row without re-writing the whole file?
Like "when updating a row in a database table, I don't have to rewrite the whole table"?
Thanks,
J.
First : plist is for very trivial data, so there should not be the question of optimisation of reading and writing it. As if you need to optimise that, that means you need to change your application design.
Second : plist is basically an xml file, so of course you can use xml parsers.
Theoretically, you could do modifications faster under the condition that the lengths of the string representation of your new value takes up precisely as many characters as that of the old value. However, this would be a bad case of micro-optimization: unlike a database where rewriting an entire table may take considerable time, rewriting a plist in its entirety should go unnoticed, as far as the timing is concerned. Your code to locate and overwrite the old value in a file would not be pretty by any standard. It has no chance of matching the clarity of a three-line "read-modify-write" code fragment that rewrites the whole thing.
This assumes that you are using your property list for its intended purpose, which is storing relatively small amounts of data. If you are using a plist to store moderate to large amounts of data, perhaps you need to switch to using a database, where updating individual rows is permitted.
Where is the sense in that?
Despite what has already been said, that plist, who use XML, is designed for small amounts of data and that it could work properly only when the new value does not make any change to the length (string representation within the XML) of your value, there is hardly any bargain to make.
Frankly I do not know what the cluster (or however the smallest fraction of allocable disk space is named in iOS' file system) size is but I would not expect it to be much smaller then the average size of a typcal plist file. In all file systems that I know a cluster will allways be written in one go. Even if the programmer just changes a byte and tries to write only that one byte back to the file, the OS will allways write the full cluster on disk (or whatever there is that we still call a disk :).
Meaning - even if you try hard, you will hardly gain anything from that attempt.
Unless of course, your data structure is rather big and probably complex for a plist file. In that case, as it has been said already, consider a change to the data storage method that you are using.
From an other answer:
You have:
a plist file
a container (for example, NSMutableArray) in which you load this plist
a table view which takes values from this container.
To modify plist through table view:
change value in container
write container back to plist file.

Which will perform better, parsing string each iteration, or parsing once and storing

I'm creating a vb.net winforms application that will take in user given strings, parse them, and print out labels with variable information. The given string will be used in all the labels, but the variable part of the string will change with each label.
My question is: is it better to parse the strings one time, then store those values in arrays, or to parse the string each time a label is printed? Which will perform better? Which is better practice? What is the proper way to test something like this?
If saving data in memory is done for performance, my preference would be not to do it until I knew the parsing was actually a performance problem, which I detect by random-pausing.
Generally my rule of thumb is - the less data structure the better.
If you have data structure you have to worry about it getting stale, and any time you change the program you have more code to modify and put bugs into.
Besides, parsing does not need to be slow, especially compared to whatever else you're doing.
Parsing is definitely heavy stuff.
In this particular instance if you do not have any memory constraints then you should parse once and store to speed up your application, especially if it is going to be something that is being used by people :)

Staggering sqlite records with Objective C

An iphone app we are producing will potentially have a table with 100,000+ records (scaling wise) and I am concerned that loading all this data via a SELECT * command into an array, or an Object will either make the app very slow; or will leave me with memory issues later on.
Obviously loading 100,000+ records into an array when the viewscreen/viewport only shows 30 odd records in a go is a tad silly.
In addition, I am not sure if storing all this data in an object is the right thing to do either.
So my question is, is it possible to stagger sqlite through records, say 50 records in cache and then when you swipe down or up it loads an appropriate amount into the cache. I guess its similar to the JQuery Lazy Loading library where it only loads a little bit on the view port and then loads more as you move down.
I'm looking at JSON, but it appears to only be for Web services as it requires a URL and I am not sure if it works for files that are on the phone.
Therefore. Is there a proper way to load sqlite data into Objective C arrays/objects without causing problems when the data suddenly starts to scale?
Thanks for your help.
You definitely want to avoid loading in everything at once. Instead, you want to use a cursor and smarter queries so that you only pull data out of the database as you actually need it for display; that link points to some hints on how to do that.
Generally, you also want to avoid blindly selecting all columns. This is because you may sometime update the schema to add a column that your existing code would not always know how to extract; far better to name the explicitly columns that you expect and desire.

Should I load everything in memory upon application start?

I'm using VB.Net, and I have a set of data which I have to able to filter through fairly quickly. Basically, the program is like google sugest, but instead of a drop-down menu, I'm using a listbox. When a user enters a word, I compare the word using LINQ and filter those that contain the user's input. The data are all strings of variable length (from 0 to 200 characters, most on 150 character mark), and I have 240,000+ of this strings and counting- all stored in an XML file.
A colleague of mine told me that loading all of that to memory (using VB.Net's XML serializer plus collections of string/objects) is not practical, and would slow the 'startup' time of the program. I haven't finished building the program yet and I'm having second thoughts about continuing this path.
So, my question is: Should I continue with my current approach on the problem (which is load everything to memory on startup), or is there a better way of solving my dilemma?
If you want to prevent startup time and keeping it in memory isn't an issue on performance, then load it asynchronously. Although loading 240.000+ strings from an XML and keeping it in memory doesn't sound like the greatest idea. Probably a database would be the better approach. Or at least some format like JSON that's faster to parse.
Depends on a number of things:
If
((you know the strings will not hugely increase in number) &&
(you know the spec of the machines that will run your app) &&
(you are able to test that the load time is *good enough* on the above spec))
{
**don't bother changing approach.**
}
else
{
**change approach.**
}
The alternative approach is obviously some kind of asynch lazy-load.
You're talking about loading roughly 36MB of strings. While this isn't a daunting amount by any means (though you could probably load it faster reading the XML yourself...I wouldn't go with the serialization engine if I was worried about performance), it's also a non-trivial amount. You're looking a adding a couple of seconds to your startup time, assuming you don't do it asynchronously as Mircea suggests.
If you do do it asynchronously, you'll have to ensure that any UI process that relies on the data doesn't occur until after it has loaded. That may be a difficult thing to ensure.
The question seems to imply an online application. A few suggestions if that is the case:
The data could / should be zipped. I suspect it would compress very nicely.
Maybe the data could be cached accross multiple sessions, possibly be delivered as html content with a expiry cache date as appropriate. This would save systematic loading, and may be feasible if the data isn't updated frequently.
The suggestion feature feature could be initially disabled (i.e. say showing a "loading..." message while the application initializes the cache, asynchronously). In this fashion the application would be quickly available upon startup, even though the suggest feature may lag by up to say 30 seconds or so.
Edit: Independently of how the data gets downloaded and cached, I second the opinion of Mircea Grelus that an xml file of this size is a poor substitute for a database.
It may not be a bad idea to load the XML into memory when the app starts up. But if you go this route I'd look into using the BackgroundWorker thread. The idea would be to load the XML into memory asynchronously so the UI is still responsive as this is going on. As far as the user is concerned the app shouldn't appear to start any slower, and yet once done the Google-suggest-like feature should be significantly faster.
I must say that even in memory this is an inherently inefficient operation since you have no advantage of using an index when querying an XML file in this way. This is something that would be 10X faster in SQL with full-text searching.
Of course XML has the advantage of being self-contained and requiring no additional components. And that makes it a decent choice for small desktop apps that query small amounts of data. Otherwise I would consider using a database for better performance.
You might be better served by using binary serialization rather than XML serialization to persist the data that your app reads on startup, particularly if you end up implementing a data structure that's faster to search than a `StringCollection. You'd still maintain the XML version of the data somewhere, of course.
And by all means, use a BackgroundWorker to load the data asynchronously if that'll make your application feel more responsive.