I am building a healthKit based app and am wondering how to best save healthKit data persistently.
My current approach is to get the data and save it as attributes of a custom class object and then save it in core data as NSData.
In terms of performance is Realm faster than CoreData?
According to http://qiita.com/moriyaman/items/1a2916f4c2b79e934370 CoreData is apparently slower than FMDB which is slower than Realm. Can someone confirm if this is true even after taking into account faults and indexes?
Disclaimer: I work at Realm
The question of which persistence product will perform best among the solutions you mentioned is highly dependent on the type/amount/frequency of your data. Since Core Data and FMDB are layers over SQLite, they can't be faster than SQLite by design, but they provide enough convenience to be worthwhile to many users. On the other hand, Realm isn't based on SQLite, but rather its own custom database engine that was designed specifically for modern smartphones. It was designed to strike a better balance between powerful features, simple API without adding a large performance hit.
You can see public benchmarks comparing Realm/SQLite/Core Data/FMDB in Realm's launch blog post here: http://realm.io/news/introducing-realm#fast
Finally, your approach of serializing HealthKit information into NSData using something like NSCoding is going to be terribly inefficient. No matter the persistence solution you choose, you'll be better served by using the serialization built in to those products rather than storing an already serialized data blob.
As I commented to #jpsim, it is difficult to simply compare the performance of Core Data to lower-level frameworks like FMDB, or differently-abstracted frameworks like Realm. Which approach you choose will dramatically impact how you build your program, which will tend to shuffle the performance problems around to different places.
Core Data and SQLite solve very different problems. SQLite is a relational database. Core Data is an object persistence engine. I'm not an expert on Realm, but it seems to be trying to strike a balance between those two approaches with more low-level control than Core Data affords, but a closer tie-in to the object model than SQLite. The fact that Realm (at least in my impressions of it) gives you more low-level control opens up opportunities for you to optimize things, or to mess things up IMO. That's neither good nor bad, it just makes it hard to apples-to-apples compare them, and particularly makes generic "performance benchmarks" problematic. The question isn't whether it's possible for someone to write faster code using engine A vs. engine B. The question is whether you will likely write acceptably performant code in each engine, while avoiding bugs, and minimizing development time.
In general, I believe HealthKit data is supposed to be stored in HealthKit in order to protect privacy. You should be careful about storing this data in your own storage anyway. Be particularly aware of the guidelines about iCloud:
Apps using the HealthKit framework that store users’ health information in iCloud will be rejected
I don't know how this will impact documents that you store and are then backed-up to iCloud. Just leaving the data in HealthKit is the best way to not have to worry about such problems.
In any case, though, performance is just one axis to consider. You didn't indicate anything to suggest that you have very special performance problems (for example, that you're handling tens of thousands of records, or real-time data, or something like that). So I would focus first on what tool meet your general needs best, and then do some basic experiments to make sure the performance is reasonable, and then optimize as you find issues.
Related
This question is different from questions here, because of the app being mostly in the background.
It is a requirement for our application that we keep the data store encrypted.
Our current implementation is using SQLite using SQLCipher. The plan is to move to Core Data.
I'm looking for a solution to keep the data encrypted, while still accessible in the background and is not restricting in terms of queries-NSPredicates and migration (schema change).
Below are all the options I've been looking into:
NSFileProtectionComplete - will not allow file access in the background
encrypted-core-data - This library does appear to be kept up-to-date. However, I've had second thoughts about using it in production after seeing the list of known issues. Has anyone used this recently?
NSIncrementalStore - This was the way that Apple engineers recommended that we follow. encrypted-core-data is using this method.
Transformable Attributes in core data - is this solution scalable for larger data sets?
Does anyone have a recommendation that meets all of the criteria and can be used in production apps?
I ran some proof-of-concept apps using each of the above options. I ran numbers and bench-maked it against our existing solution (SQLCipher).
Looks like using core data with incremental store (encrypted-core-data) came out to be the best.
After analyzing runtime performance times for read, write and search on DB with small and large sizes, encrypted-core-data turned out to be the most efficient and simpler to implement.
I'm trying to write a iOS note taking app that is blazingly fast for a large number of notes and that syncs without ever blocking the UI. (Don't worry, it's just a learning project, I know there are a billion note apps for iOS). I have decided to use Core Data (mostly because of the excellent posts by Brent Simmons about Vesper). I know UIManagedDocument can do async reads and writes and has a lot of functionality built in, so I'm wondering if there is any information on which would be faster for a fairly simple notes app. I can't really find a lot of information about people using UIManagedDocuments for anything other than a centralized, basically singleton, persistent store. Is it suitable for 1000s of documents? Would it be faster or slower than just a database of NSManagedObjects? It seems like most information I can find about Core Data is oriented towards people using NSManagedObject, so any information about UIManagedDocuments being used in production apps would be really helpful. At this point, the only thing I can think of is to just write the whole app both ways, load 10,000 notes into it, and see what happens.
Update
To clarify, I'm not learning iOS development and Objective-C, the "learning project" mostly means that I've never used Core Data and would like to learn how to write a really performant Core Data application.
UIManagedDocument is designed/intended for document based applications. One UIManagedDocument instance per document. If you are not building a document based application then you should not be using UIManagedDocument.
Everything that people like about UIManagedDocument can be accomplished with very little effort using the Core Data stack directly. UIManagedDocument abstracts you away from what your persistence layer is doing. Something you really do not want.
If you want a high performance Core Data application you do not want to be using UIManagedDocument. You will run into issues with it. It will do things at random times and cause performance issues.
You are far, far, better off learning the framework properly.
In the case of Vesper, those are not documents; they are too small. Think of documents as Word files, or Excel files. Large complicated data structures that are 100% isolated from each other.
Also, whether you use a UIManagedDocument or not, you will be using NSManagedObject instances. NSManagedObject, NSManagedObjectContext, NSPersistentStoreCoordinator are all foundational objects in Core Data. UIManagedDocument is just an abstraction layer on top.
Finally, Core Data is not a database. Thinking of it that way will get you into a jam. Core Data is an object model that can persist to disk and one of the persistence formats happens to be SQLite.
Update (Running Into Problems)
UIManagedDocument is an abstraction on top of Core Data. To use UIManagedDocument you actually need to learn more about Core Data than if you just used the primary Core Data stack.
UIManagedDocument uses a parent/child context internally. Don't understand that yet? See the point above. What it also means is that your requests for it to save are "taken under advisement" as opposed to being saved right then and there. This can lead to unexpected results if you don't understand the point of it or don't want it to save when it feels like it.
UIManagedDocument uses asynchronous saves and at most you can request that it save. Doesn't mean it is going to save now, nor does it mean you can easily stop and wait for the save to complete. You need to trust that it will complete it. In addition, it may decide to save at an inopportune moment.
When you start looking for performance gains with Core Data you tend to want to build the stack in a very specific way to maximize the benefit to your application. That is application dependent and with the abstracts in UIManagedDocument you get limited very quickly.
Even in a situation where I was building a document based application I would still not use UIManagedDocument. Just to much behind the curtain.
Performance is likely to come down to how the rest of your code is implemented, and not necessarily the difference between a UIManagedDocument or a NSManagedObject.
Think of UIManagedDocument as a specific niche implementation of CoreData, that already has the parts of CoreData you want baked into it's structure to save you (the developer) a little bit of time writing code. It's been purpose built for handling UIDocuments, and multi-threading.
Under the hood, it's likely that UIManagedDocument is using CoreData as well as you would (assuming you know what you're doing), but it's theoretically possible you could cut some corners by knowing the exact and inane details of your implementation.
If you're new to CoreData, or GCD and NSOperationQueue, then you'll likely save a ton of developer time by leveraging UIManagedDocument instead of rolling your own.
A very apt analogy would be to using a NSFetchedResultsController to run your UITableView, rather then rolling your own CoreData and UITableView implementation.
If you're new to objective-C, I'd recommend you bang out something functional with UIManagedDocument at first. Later you get lost in the weeds of dispatch_asynch() and NSFetchRequest, and pick up a few milliseconds of performance here and there.
Cheers!
Just store a plain text file on the disk for each note.
Keep a separate database (using sqlite or perhaps just -[NSDictionary writeToFile:atomically]) to store metadata, such as the last user modification date and the last server sync date for each note.
Periodically talk to the server, asking it for a list of stuff that has changed since the last time you did a sync, and sending any data on your end that has changed in the same time period.
This should be perfectly fast as long as you have less than a million note files. Do all network and filesystem operations on an NSOperationQueue.
I am trying to build an app for my website. I was under the impression that all I had to do was get and put json from the server to my phone. But then today I came across Core Data ( I am new to iOS).
So my question is, that to make a faster iOS app, is it a normal practice to fetch json data and save it as core data? Would apps like Facebook, Twitter follow this approach? or is just fetching and parsing json is a normal practice, and core data is not needed.
I am sorry if the question is dumb.
It is normal to retrieve data from a server (XML or JSON) and keep it in memory, if the memory foot print is reasonable. If you are talking about hundreds upon thousands of rows from a database, then persistent storage, with a dedicated data model(s) is probably the best choice; you can read it when needed.
If your needs are such that a complex data model is needed, one-to-many and/or many-to-many relationships, then consider Core Data (or SQLite directly).
You define your needs first, then try to define the data model that fits your needs (custom objects or maybe just a few instances of NSDictionary), then decide how that data needs to persist and how you plan on interacting with that data.
A few starting points:
Core Data Overview - Shoud help you decide if you should use it
RestKit - Just a suggestion
Tutorial on Data Persistence
Good luck.
I remember facing this anomaly not so long ago.
As already pointed out in some of the comments, it depends on your needs.
Not all data are eligible to be saved in core data after retrieving it from the web side. You might have integrity issues with that. To do the checks for large chunks of data might have even severe overheads. But if you feel that certain data are not likely to change very often then you can employ this technique for some portions.
If you decide to stick with Request/Fetch data, be sure you process the requests using NSOperation, GCD or NSThread, in order to avoid UI freezes.
Although, they are used for same purpose, they all have advantages and disadvantage, plz check out this topic on NSOperation vs Grand Central Dispatch
I hope this helps.
My iOS app requires little local data, average user won't user more than 1 MB, but it does many queries(fetches) with predicate, so I'm thinking loading the whole sqlite file into memory when I launch to improve query speed, but I didn't see a way to do that.
So I'm thinking using NSBinaryStoreType, while will be loaded into memory when app launches, and queries much faster, am I doing right?
user465191,
Rather than speculate on the performance differences, perhaps you should just try both types? It is extremely easy to create and use both store types.
In reality, every app has a working set. Core Data's managed object contexts and store coordinators (and, I add, SQLite itself) are quite good at caching information. I doubt you will see little difference on a database of your size.
As in all engineering endeavors, use data to guide your hand. Your app is different than mine. I would love to know the results of your comparison. Your mileage will vary.
Andrew
I've developed quite a few local apps, however this is the first time I'm introducing networking (more specifically posting to, and reading from a database). I am receiving back a JSON object from the database but I am currently using arrays and dictionaries. The objects do have relationships to each other, and I was wondering whether CoreData is the way to go. If so, do I just replicate part of the database I wish to be made viewable in the app and store it in my CoreData model? Are there any tutorials out there for this?
Also, just as a side note, I've also included Facebook integration with which I download the users list of friends. Would CoreData be good for storing this kind of information too? Or would I be better sticking with dictionaries?
Thanks in advance.
Based on my experience (other could say different things) Core Data is the right choice but its adoption could depend on the time you could dedicate to it. At first could be very complicated but I think you could take advantage applying the knowledge in some other projects.
Out of there there are some tutorials or books on Core Data.
First I suggest to read about core-data-on-ios-5-tutorial-getting-started. In the site there are, I think, other tutorials. Then, you could try to read a post on core data I've written some time ago: Mapping Business Objects with Core Data in iOS. Also Apple doc is your friend. So read the Introduction to Core Data Programming Guide to have the details that are going on.
If so, do I just replicate part of the database I wish to be made
viewable in the app and store it in my CoreData model?
Yes, just a part. You can create a minimal model that includes the key parts you need to have in your device. What I want to highlight is that you don't need to take care of normalization concepts when you deal with Core Data. Yes you could, but in CD you deal with objects and it's important to make attention to memory consumption (the framework helps you) and performances.
Would CoreData be good for storing this kind of information too? Or
would I be better sticking with dictionaries?
With CD you could take advantage of NSFetchedResultsController. A NSFetchedResultsController objects is optimized to work with tables and it used to display data also in batches. Through this component you can deal with a lot of elements (say friends in Facebook) without overload the memory. See core-data-tutorial-how-to-use-nsfetchedresultscontroller.
If you want to know something else, let me know.
Hope that helps.