访问文件属性与访问sqlite记录

Seg*_*gev 7 sqlite iphone objective-c nsfilemanager ios

在我们的一个应用程序中,我被要求记录上次修改的图像日期.这样我可以检查服务器是否已更改某个映像并相应地更新我的缓存.

我的第一种方法是访问文件属性并进行比较,但在线的一些地方提到了延迟方面的严重瓶颈.

我的第二选择是创建一个SQLite表来管理它.(使用fmdb)

我决定编写一个简单的延迟测试.在下一个测试中,我正在访问500个文件属性和500个sqlite记录:

- (void)latencyTest
{
    NSMutableArray *arrayTest1 = [[NSMutableArray alloc]init];
    NSMutableArray *arrayTest2 = [[NSMutableArray alloc]init];
    FMResultSet *results = [_database executeQuery:@"SELECT * FROM `tb_media`"];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"dd-MM-yyyy HH:mm:ss:SSS"];
    NSLog(@"Time1: %@",[formatter stringFromDate:[NSDate date]]);
    int i=1;
    while(i<501)
    {
        NSString *test = [NSString stringWithFormat:@"%@/_media/media/19/%d.jpg",_outputPath,i];
        NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:test error:nil];
        NSDate *dateX = [attributes fileModificationDate];
        [arrayTest1 addObject:dateX];
        i++;
    }
    NSLog(@"Time2: %@",[formatter stringFromDate:[NSDate date]]);
    while([results next])
    {        
        NSDate *myDate = [NSDate dateWithTimeIntervalSince1970:[results intForColumn:@"last_update"]];
        [arrayTest2 addObject:myDate];
    }
    NSLog(@"Time3: %@",[formatter stringFromDate:[NSDate date]]);
}
Run Code Online (Sandbox Code Playgroud)

结果:

    //iPhone 5 (Actual Device) 500 Pics

    Files Start:                 05-03-2014 09:31:20:375 
    Files End & Sqlite start:    05-03-2014 09:31:20:491 
    Sqlite end:                  05-03-2014 09:31:20:507

    Files Start:                 05-03-2014 09:31:56:305 
    Files End & Sqlite start:    05-03-2014 09:31:56:421 
    Sqlite end:                  05-03-2014 09:31:56:437

    Files Start:                 05-03-2014 09:32:19:053 
    Files End & Sqlite start:    05-03-2014 09:32:19:170 
    Sqlite end:                  05-03-2014 09:32:19:187
Run Code Online (Sandbox Code Playgroud)

如您所见,结果几乎相同.我的问题是:

  1. 我假设一次访问一个文件attributesOfItemAtPath将花费比sql更长的时间.我错过了什么吗?

  2. 是否attributesOfItemAtPath真的访问文件或文件系统的iOS在保持某种形式的数据库,方便访问所有的属性?

  3. 看到上面的结果后,我决定采用这种 attributesOfItemAtPath方法.还有什么我不考虑传递sqlite吗?

Kun*_*ani 5

在讨论解决方案之前,您的评估策略存在一些问题.

1)您没有纳入NSLog和while循环所花费的时间.75%的时间是由他们采用的,而您只是想比较intForColumn和attributesOfItemAtPath.执行此操作的正确方法是运行仪器 Timer Profiler并比较检索单个记录的时间.

2)您已将FMDB用作文件管理器.内部FMDB序列化文件中的数据.FMDB/SQL Lite的核心在于其数据结构,特别是您根本没有使用过的索引.因此,即使您比较记录所花费的时间,您将观察FMDB比文件管理器花费更多时间,因为以特定格式序列化数据需要额外的开销.

3)通过访问磁盘(硬盘驱动器)而不是堆的次数来比较X个记录的访问时间.您正在做的是在两种情况下都对数据存储进行堆访问.因此,您将无法看到任何差异.

这是否意味着文件管理器比FMDB更好,绝对不是!! 以下是几个原因:

FMDB只有在配置完成后才能正常运行.FMDB的核心在于分页(缓存到堆)和索引两个方面.让我一次向你解释一下.

1)假设您正在尝试访问100张图像的时间戳.每个图像有1000个时间戳.这意味着您必须对数据存储进行100*1000 = 100,000访问.如果图像很小,那么Filemanager会将文件加载到堆中,访问速度会比FMDB快,但是如果没有足够的堆空间,应用程序将发出内存警告并从磁盘访问文件而不是缓存,这要慢得多.

所以它是一个二进制状态,要么全部来自堆,要么来自磁盘

FMDB优于此状态并根据可用堆空间检索部分记录.当您有大量记录时,这会使访问速度更快.

测试此场景的理想方法是为至少10,000个图像(不是时间戳)运行您的fumpntion latencyTest.这样,与所花费的总时间相比,对数时间和迭代速度可以忽略不计.

2)索引结构,这可以追溯到SQL Lite的基础知识.您可能希望添加额外的属性调用作为对图像的访问次数,并在其上编制索引.这将大大提高人均力量.Filemeanger不太可能.

我推荐的解决方案.
1)如果您的数据小于2 MB(图像加时间戳),请转到Filemenager

2)如果数据大于2MB,则转到Core Data/FMDB.

核心数据针对多线程环境进行了额外的性能调整,还有许多其他功能,如无缝集成加密.