IOS Cache设计
Cache的设计是个基础计算机理论,也是程序员的重要基本功之一。Cache几乎无处不在,CPU的L1 L2 Cache,iOS系统的clean page和dirty page机制,HTTP的tag机制等,这些背后都是Cache设计思想的应用。
为什么需要Cache
Cache的目的是为了追求更高的速度体验,Cache的源头是两种数据读取方式在成本和性能上的差异。
在开始着手设计Cache之前,需要先理清数据存储的媒介。作为客户端开发人员来说,我们所关注的数据存储方式也有不少种:
数据最开始是存储在Server上,这些数据需要通过网络请求获取。 从Server获取数据时,会经过各种中间网络节点(比如代理),这些节点有时会缓存我们的数据。 把数据下载到本地之后,我们会在本地disk缓存一份,这样或许不用每次都重新去服务器请求。 存到disk之后,数据的存储方式会影响到读取的速度,以B+ Tree存储的sqlite就比直接序列化NSArray到文件之中要快不少。 App启动时,系统会将从Server下载到的数据,从disk加载到memory,memory的读写性能比disk要快很多。 到了Memory中,不同的数据结构存储方式也会存在速度上的差异。用NSDictionary(hash表)形式存储读数据,写性能都比Array好,但space开销更大。虽说memory的读写性能比disk都高了很多,但在大集合类数据操作的时候有时也会遇到瓶颈。 比Memory更快的还有Register,L1,L2,只不过对于iOS App开发来说,很少深入到这一层面的优化。上面所说的每一个环节,都存在性能和成本上的差别,Server的数据自然是最及时最准确的,但一个App要以NSArray的形式获取到Server的数据,中间要经过「漫长」的过程,可以说每一步中都存在cache的设计思想。
对于Cache的理解和实践,前提是我们对于存储媒介,和不同数据结构差异,有比较深入的掌握。
我们大部分App的性能优化,如果涉及到Cache,一般都是在Memory这一媒介上做处理。将需要从Disk中,或者通过CPU复杂计算才能获取的数据,通过合理的数据结构存储在Memory中,就能解决我们App开发里,绝大部分的Cache需求了。这一层面的Cache设计也有着不同的姿势,先来看看简单可用型。
简单可用型Cache
得益于Foundation中NSDictionary的封装,我们可以用hash表这种数据结构来实现一个简单可用的cache机制,先来看一个实例:
- (NSString*)getFormmatedPhoneNumber:(NSNumber*)phone
{
if(phone == nil)
{
return nil;
}
return [PhoneFormatLib formatPhoneNumber:phone]; //CPU费时操作
}
这是个简单的格式化手机号码的函数,其中 formatPhoneNumber 函数是个CPU Intensive的调用,而且在业务场景中针对同一个手机号码,需要经常性的获取格式化之后的NSString,如果每次都重复计算显然是对CPU资源的浪费,而且性能也不好。我们可以加个简单的Cache来优化:










