What's the effect of cache to NSFetchedResultsController - ios

I read the doc of course, but I don't quite get the meaning of "setting up any sections and ordering the contents".
Don't these kinds of information come form data base?
Does it mean NSFetchedResultsController needs some other kinds of indices itself beside data base indices?
What's really going on when NSFetchedResultsController is setting up a cache?
Is cache useful for static data only? If my data update frequently, should I use cache or not?
How can I profile the performance of cache? I tried cache, but couldn't see any performance improvement. I timed -performFetch: but saw a time increase from 0.018s(without cache) to 0.023s(with cache). I also timed -objectAtIndexPath: and only a time decrease from 0.000030(without cache) to 0.000029(with catch).
In other words, I want to know when cache does(or does not) improves performance and why.
As #Marcus pointed below, "500 Entries is tiny. Core Data can handle that without a human noticeable lag. Caching is used when you have tens of thousands of records." So I think there are few apps that would benefit from using cache.

The cache for the NSFetchedResultsController is a kind of short cut. It is a cache of the last results from the NSFetchRequest. It is not the entire data but enough data for the NSFetchedResultsController to display its results quickly; very quickly.
It is a "copy" of the data from the database that is serialized to disk in a format that is easily consumed by the NSFetchedResultsController on its next instantiation.
To look at it another way, it is the last results flash frozen to disk.

From the documentation of NSFetchedResultsController:
Where possible, a controller uses a cache to avoid the need to repeat work performed in setting up any sections and ordering the contents
To take advantage of the cache you should use sectioning or ordering of your data.
So if in initWithFetchRequest:managedObjectContext:sectionNameKeyPath:cacheName: you set the sectionNameKeyPath to nil you probably won't notice any performance gain.

From the documentation
The Cache Where possible, a controller uses a cache to avoid the need
to repeat work performed in setting up any sections and ordering the
contents. The cache is maintained across launches of your application.
When you initialize an instance of NSFetchedResultsController, you
typically specify a cache name. (If you do not specify a cache name,
the controller does not cache data.) When you create a controller, it
looks for an existing cache with the given name:
If the controller can’t find an appropriate cache, it calculates the
required sections and the order of objects within sections. It then
writes this information to disk.
If it finds a cache with the same name, the controller tests the cache
to determine whether its contents are still valid. The controller
compares the current entity name, entity version hash, sort
descriptors, and section key-path with those stored in the cache, as
well as the modification date of the cached information file and the
persistent store file.
If the cache is consistent with the current information, the
controller reuses the previously-computed information.
If the cache is not consistent with the current information, then the
required information is recomputed, and the cache updated.
Any time the section and ordering information change, the cache is
updated.
If you have multiple fetched results controllers with different
configurations (different sort descriptors and so on), you must give
each a different cache name.
You can purge a cache using deleteCache(withName:).

Related

we know data cache for row data and index cache for group values. does aggregator process all the data to cache before its operation?

Can you please help me to understand this by taking below example.
Group by cust_id,item_id.
what records will process to caches(index/data) in both scenarios with sorted input and unsorted input?
What will be case if cache memory runs out?Which alogritham it uses to perform aggregate calculations internally?
I don't know about internal algorithm, but in unsorted mode, it's normal for the Aggregator to store all rows in cache and wait for the last row, because it could be the first that must be returned according to Aggregator rules ! The Aggregator will never complain about the order of incoming rows. When using cache, it will store rows first in memory, then when the allocated memory is full, it will push cache to disk. If it runs out of disk space, the session will fail (and maybe others because of that full disk). You will have to clean those files manually.
In sorted mode, there is no such problem : rows come in groups ready to be aggregated and the aggregated row will go out as soon as all rows from a group are received, which is detected when one of the values of the keys changes. The Aggregator will complain and stop if rows are not in expected order. However it pushes the problem upward to the sorting part, that could be a Sorter, which can use a lot of cache itself, or the database with an ORDER BY clause in the SQL query that could take resources on the database side.
Be careful also that SQL ORDER BY may use a different locale than Informatica.

Core Data under the hood memory usage

So I am a bit confused about the amount of copies core data keeps for every managed object. First it stores a copy in the row cache which it uses to fulfill faults. Then for every object it also keeps a snapshot of the unmodified object as well as the actual data for the object (assuming its not a fault). That's 3 copies for one object so I assume I am misunderstanding something. This would mean migrations would need 4 times the size of the objects in the original database as it also has to create a new destination stack. I assume core data is smart and may do things like copy-on-write under the hood and not create a snapshot unless the object is actually modified.
Could someone please explain what is wrong about my thought process? Also is it true that the row cache will be shared by different managed object contexts created from the same persistent coordinator, or is there a row cache for each context?

How to use NSCache appropriately in iOS application?

I am building an application and want to use NSCache to store data for caching.
There will be approx 5 API for which I need to cache data. Should I user NSCache? I did research for NSCache but I have some doubts regarding this.
I did go through below link.
https://developer.apple.com/library/content/documentation/Performance/Conceptual/ManagingMemory/Articles/CachingandPurgeableMemory.html
I found some interesting things there.
NSCache provides two other useful "limit" features: limiting the number of cached elements and limiting the total cost of all elements in the cache. To limit the number of elements that the cache is allowed to have, call the method setCountLimit:. For example, if you try to add 11 items to a cache whose countLimit is set to 10, the cache could automatically discard one of the elements.
If we set limit to 10 and if we try to add 11th item then which particular item it will discard that is 1st one or 10th one? Or it can be a random item.
If I want to store 5 different NSCache object for all APIs then how can I do it?
I should make 5 different NSCache objects or I should store 5 different dictionary in single NSCache object?
Please let me know the best way to deal with it.
NSCache works basically as an NSMutableDictionary, the main difference is that even if is mutable is thread safe (usually mutable NSFoundation objects are not thread safe). So you get and set objects using keys.
Yes, the documentation is not clear, but I remember (and it makes sense) that is written that you should always detect if an object is cache and if not reload it from your primary source or manage that particular case. So it is not very important which one is removed, just make sure that at some point an object can not be there anymore and you are managing that situation.
I usually create different caches based on different context, but most of the time one would suffice.
I have few advices:
Your answer is tagged as Swift, thus pay attention that NSCache (in swift 2, don't know in 3) works only with objects and not struct or enumerations (value types unless thay can be bridged).
Remember that http protocol has its own cache system and communication, do not reinvent the wheel

What is the transient, indexed, index spotlight and store in external Record file in core data?

I want to know when to use below properties? What do they do? Why should we use it?
Transient: According to Apple Docs:
Transient attributes are properties that you define as part of the
model, but which are not saved to the persistent store as part of an
entity instance’s data. Core Data does track changes you make to
transient properties, so they are recorded for undo operations. You
use transient properties for a variety of purposes, including keeping
calculated values and derived values.
I do not understand the part that it is not saved to the persistent store as an entity instance's data. Can any one explain this?
indexed: It increase the search speed but at the cost of more space. So basically, if you do a search query using an attribute and you want faster result then make that property as 'indexed'. If the search operation is very rare then it decreases the performance as it take more space for indexing.
I am not sure whether it is correct or not?
index in spotlight
Store in External record file
Consider for instance that you have a navigation app. On your map you have your car at the center, updated a few dozen times a second, and an Entity of the type "GAS STATION". The entity's property 'distance' from your car would be a transient property, as it is a function of real time data thus there's no point to storing it.
An indexed attribute is stored sorted, therefore it can be searched faster. Explanation can be found on Wikipedia. If your frequent searches take noticeable time, you should probably consider indexing.
Consider indexing in Spotlight anything the user is likely to want to search for when not within your application. Documentation is here.
Large binary objects, like images, should be stored externally.

Deleting specific keys from memcached hash

I am trying to cache a table t_abc using memcached, for my rails application. The table has 50,000 entries. And I finally want have 20,000 keys(which will be of the form "abc_"+id). When the 20,001st entry is to be inserted in the cache, I want the least recently used key out of these 20,000(of the above form, and not some other keys in the memcached) to be deleted from the cache. How do I achieve that?
NOTE: I am keeping an expiry = 0 for all the entries.
No, unfortunately you cannot efficiently do what you want to do with memcached.
It has a single LRU which works across all the data you are storing. So if you are storing data from multiple tables then the fraction of the memcached entries taken up by each table depends on the relative patterns of access of the data from the different tables.
So to control the amount of rows of the table are cached, really all you can do is adjust how big your memcached is and vary what other data gets stored.
(Also, to evaluate the memcached configuration you might consider using a different metric, such as the hit rate or the median response time, rather than simply the number of rows cached.)

Resources