Accessing files attributes vs accessing sqlite records Accessing files attributes vs accessing sqlite records sqlite sqlite

Accessing files attributes vs accessing sqlite records


Before I discuss the solution , there are certain problems in your evaluation strategy.

1) You haven't incorporated time taken by NSLog and while loop. 75% of time is taken by them whereas you just want to compare intForColumn vs attributesOfItemAtPath. A correct way of doing this is run instruments Timer Profiler and compare time for retrieving a single record.

2) You have used FMDB as a file manager. Internally FMDB serialize data in a file. The core of FMDB / SQL Lite lies in its data structure specially indexing which you haven't used at all. So even if you compare time taken for your records you will observer FMDB is taking more time than file manager because of extra overhead to serialize data in specific format.

3) Access time of X number of records is compared by the # of times access is done to disk (hard drive) not heap. What you are doing is heap access of data store in both cases. So you won't be able to see any difference at all.

Does this mean File Manager is better than FMDB , absolutely not!!Here are few reasons why :

FMDB performs well only when its configured to do so. The core of FMDB lies in two things paging (caching into heap) and index.Let me explain you each one at a time.

1)Assume that you are trying to access timestamp for 100 images. Where each image is having 1000 timestamps. This mean you have to make 100*1000 = 100,000 access to data store. If images are small then Filemanager will load the file into heap and access will be faster than FMDB but if you don't have sufficient heap space your application will issue memory warning and access file from disk rather than cache which is significantly slower.

So its a binary state either all from heap or all from disk

FMDB outperforms this state and retrieves partial records depending upon the available heap space. This makes access faster when you have a huge chuck of records.

The ideal way to test this scenario is to run your fucntion latencyTest for atleast 10,000 images (not timestamp). This way the log times and iteration speed will be negligible as compared to overall time taken.

2) Index structure, this goes back to the basics of SQL Lite. You might want to add an extra attribute call as number of access to images and index your table on that. This will boost up perforce significantly. Not quite possible with Filemeanger.

Solution which I recommend.
1) If you have data less than 2 MB (images plus timestamp ) go for Filemenager

2) If data is > 2MB go for Core Data / FMDB.

Core data has additional performance tuning for multithreaded environment and many more additional features like seamless integration for encryption.


First, as @kunal said, your benchmarking method is not deterministic and can mislead your decisions.

Having said that, attributesOfItemAtPath: does a little bit of overhead if you only need the modified date and performance is really an issue for you. What you can do is use lstat instead. This is similar to your case (Note that I removed the arrays to avoid unneeded overhead on the benchmark):

#import <sys/stat.h>- (void)latencyTest{    // *********************** Test 1 ***********************************//    double t = CACurrentMediaTime();    for (NSInteger i = 1; i < 748; i++)    {        NSString *path = [NSString stringWithFormat:kMediaPath, i];        NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path                                                                                    error:nil];        NSDate *dateX = [attributes fileModificationDate];    }    double total = CACurrentMediaTime() - t;    NSLog(@"Total time fileManager: %fs, average per read: %fs", total, total / 747.f);    // *********************** Test 2 ***********************************//    struct stat linfo;    t = CACurrentMediaTime();    for (NSInteger i = 1; i < 748; i++)    {        NSString *path = [NSString stringWithFormat:kMediaPath, i];        lstat([path cStringUsingEncoding:NSUTF8StringEncoding], &linfo);        NSDate *dateX = [NSDate dateWithTimeIntervalSince1970:linfo.st_mtime];    }    total = CACurrentMediaTime() - t;    NSLog(@"Total time lstat: %fs, average per read: %fs", total, total / 747.f);}

For an input of 748 images, my results are:

// Simulator (iOS 7.1)Total time fileManager: 0.061365s, average per read: 0.000082sTotal time lstat: 0.004313s, average per read: 0.000006s// iPhone 5s Device (iOS 7.1)Total time fileManager: 0.019299, average per read: 0.000026Total time lstat: 0.008520, average per read: 0.000011