Iphone 在内存受限的多线程iOS应用程序中存储大量非结构化数据的最佳方法?
几个月来,我一直在我的应用程序中绕圈子解决这个问题。我已经尝试了许多自制的解决方案,并将解释我在这里的工作,但我希望有人能提出一个更好的解决方案,我错过了 基本问题是:我有(可能)数千个项目需要我的应用程序随时访问。NSMutableDictionary通常是我表示每个项的第一种方法,因为每个项可能有几个到数百个属性。但其余的要求让事情变得棘手:Iphone 在内存受限的多线程iOS应用程序中存储大量非结构化数据的最佳方法?,iphone,objective-c,xcode,Iphone,Objective C,Xcode,几个月来,我一直在我的应用程序中绕圈子解决这个问题。我已经尝试了许多自制的解决方案,并将解释我在这里的工作,但我希望有人能提出一个更好的解决方案,我错过了 基本问题是:我有(可能)数千个项目需要我的应用程序随时访问。NSMutableDictionary通常是我表示每个项的第一种方法,因为每个项可能有几个到数百个属性。但其余的要求让事情变得棘手: 每个项目都可以由任何线程读取或写入 每个项目都需要存储到磁盘,以便在会话之间检索 有(可能)太多的项(和太多的数据),如果同时将它们全部放在内存中,可
- (NSObject*) getValue:(NSString*)key {
@synchronized(self) {
if(!_cached_obj) { // private variable in this object
_cached_obj = [self loadFromDisk]; // simply loads the NSDictionary from a file
}
_last_access = time(nil);//don't release for a while
return [_cached_obj valueForKey:key];
}
}
- (void) setValue:(NSObject*)value forKey:(NSString*)key {
@synchronized(self) {
[self getValue:key];//ensures the cache is active
[_cached_obj setValue:value forKey:key];
_needs_save = true;
}
}
- (void) clean {
if(!_cached_obj)
return;
@synchronized(self) {
if(_needs_save)
{
[self writeToFile];//writes the cache obj to a file
_needs_save = NO;
}
NSTimeInterval elapsed = time(nil) - _last_access;
if(elapsed > 20)
{
[_cached_obj release];
_cached_obj = nil;
}
}
}
- 当我需要一个项目的数据时,会调用getValue函数。它尝试使用缓存对象(NSMutableDictionary)。如果缓存对象为空,则在返回之前从磁盘加载对象
- setValue函数按预期工作,但也设置保存标志
- “clean”函数由后台线程在10秒计时器上运行。这负责将项目保存到磁盘并取消缓存数据以节省内存
编辑:更多信息:
“getValue”函数返回的速度也是非常重要的,即使它没有阻塞主线程。例如,考虑我在后台线程中通过10K项搜索的场景。我需要从每个10k对象中获取一个值。按照我目前的机制,它可以工作,但是从磁盘加载每个非缓存对象非常耗时,在我的iPhone4上需要大约20秒。我知道这可能只是“我必须付出的代价”。但是,也许将数据存储在较小的数据块中会有所帮助?例如,不要将整个项目存储为字典,而是存储为不同对象的集合。据我所知,您分析了应用程序,配置文件显示@synchronize块是最大的性能瓶颈。对吧? 好吧,我并不太惊讶:正如您所指出的,您在按住互斥键的同时读写文件。此外,您同时只允许一个线程,而您可以轻松地允许多个读卡器或一个写卡器访问缓存 确定的锁定操作:
- 获取值->在缓存中获取值,在磁盘上获取值如果不在缓存中,将值放入缓存
- 设置值->在缓存中获取值,如果不在缓存中,则在磁盘上获取值,将值放入缓存,将新值放入缓存
- 清理->保存缓存,清空缓存
- 在缓存中获取值
- 获取磁盘上的值
- 将值放入缓存
- 保存缓存
- 空缓存
我不会说修改锁就足够了,您可能还需要改进数据读取和保存到磁盘的方式,但要从锁开始。您可能会感到惊讶。您能更深入地解释一下您正在处理的数据吗?您的用例是什么?为什么要处理这么多具有可变或动态结构的项?您是否考虑过只运行
clean
以响应内存警告,以此作为减少缓存未命中的一种方法?您还可以通过在后台为您想要的“单个值”编制索引来获取值,但这取决于事物变化的频率。