IOS缓存管理之YYCache使用详解
发布时间 - 2026-01-11 03:09:10 点击率:次前言:

最近一直在致力于为公司app添加缓存功能,为了寻找一个最佳方案,这几天先做个技术预研,经过这两天的查找资料基本上确定了两个开源框架进行选择,这两个开源框架分别是:PINCache、YYCache,上篇已经简单介绍了PINCache使用,本篇主要来学习一下YYCache的使用方式,以及和PINCache性能的简单对比。
关于YYCache
1. 内存缓存(YYMemoryCache)
存储的单元是_YYLinkedMapNode,除了key和value外,还存储了它的前后Node的地址_prev,_next.整个实现基于_YYLinkedMap,它是一个双向链表,除了存储了字典_dic外,还存储了头结点和尾节点.它实现的功能很简单,就是:有新数据了插入链表头部,访问过的数据结点移到头部,内存紧张时把尾部的结点移除.就这样实现了淘汰算法.因为内存访问速度很快,锁占用的时间少,所以用的速度最快的OSSpinLockLock
2. 硬盘缓存(YYDiskCache)
采用的是文件和数据库相互配合的方式.有一个参数inlineThreshold,默认20KB,小于它存数据库,大于它存文件.能获得效率的提高.key:path,value:cache存储在NSMapTable里.根据path获得cache,进行一系列的set,get,remove操作更底层的是YYKVStorage,它能直接对sqlite和文件系统进行读写.每次内存超过限制时,select key, filename, size from manifest order by last_access_time desc limit ?1会根据时间排序来删除最近不常用的数据.硬盘访问的时间比较长,如果用OSSpinLockLock锁会造成CPU消耗过大,所以用的dispatch_semaphore_wait来做.
YYCache使用
1.同步方式
//模拟数据 NSString *value=@"I want to know who is lcj ?"; //模拟一个key //同步方式 NSString *key=@"key"; YYCache *yyCache=[YYCache cacheWithName:@"LCJCache"]; //根据key写入缓存value [yyCache setObject:value forKey:key]; //判断缓存是否存在 BOOL isContains=[yyCache containsObjectForKey:key]; NSLog(@"containsObject : %@", isContains?@"YES":@"NO"); //根据key读取数据 id vuale=[yyCache objectForKey:key]; NSLog(@"value : %@",vuale); //根据key移除缓存 [yyCache removeObjectForKey:key]; //移除所有缓存 [yyCache removeAllObjects];
2.异步方式
//模拟数据
NSString *value=@"I want to know who is lcj ?";
//模拟一个key
//异步方式
NSString *key=@"key";
YYCache *yyCache=[YYCache cacheWithName:@"LCJCache"];
//根据key写入缓存value
[yyCache setObject:value forKey:key withBlock:^{
NSLog(@"setObject sucess");
}];
//判断缓存是否存在
[yyCache containsObjectForKey:key withBlock:^(NSString * _Nonnull key, BOOL contains) {
NSLog(@"containsObject : %@", contains?@"YES":@"NO");
}];
//根据key读取数据
[yyCache objectForKey:key withBlock:^(NSString * _Nonnull key, id<NSCoding> _Nonnull object) {
NSLog(@"objectForKey : %@",object);
}];
//根据key移除缓存
[yyCache removeObjectForKey:key withBlock:^(NSString * _Nonnull key) {
NSLog(@"removeObjectForKey %@",key);
}];
//移除所有缓存
[yyCache removeAllObjectsWithBlock:^{
NSLog(@"removeAllObjects sucess");
}];
//移除所有缓存带进度
[yyCache removeAllObjectsWithProgressBlock:^(int removedCount, int totalCount) {
NSLog(@"removeAllObjects removedCount :%d totalCount : %d",removedCount,totalCount);
} endBlock:^(BOOL error) {
if(!error){
NSLog(@"removeAllObjects sucess");
}else{
NSLog(@"removeAllObjects error");
}
}];
YYCache缓存LRU清理
LRU(Least Recently Used)算法大家都比较熟悉,翻译过来就是“最近最少使用”,LRU缓存就是使用这种原理实现,简单的说就是缓存一定量的数据,当超过设定的阈值时就把一些过期的数据删除掉,比如我们缓存10000条数据,当数据小于10000时可以随意添加,当超过10000时就需要把新的数据添加进来,同时要把过期数据删除,以确保我们最大缓存10000条,那怎么确定删除哪条过期数据呢,采用LRU算法实现的话就是将最老的数据删掉。接下来我们测试一下
YYCache *yyCache=[YYCache cacheWithName:@"LCJCache"]; [yyCache.memoryCache setCountLimit:50];//内存最大缓存数据个数 [yyCache.memoryCache setCostLimit:1*1024];//内存最大缓存开销 目前这个毫无用处 [yyCache.diskCache setCostLimit:10*1024];//磁盘最大缓存开销 [yyCache.diskCache setCountLimit:50];//磁盘最大缓存数据个数 [yyCache.diskCache setAutoTrimInterval:60];//设置磁盘lru动态清理频率 默认 60秒
模拟一下清理
for(int i=0 ;i<100;i++){
//模拟数据
NSString *value=@"I want to know who is lcj ?";
//模拟一个key
NSString *key=[NSString stringWithFormat:@"key%d",i];
[yyCache setObject:value forKey:key];
}
NSLog(@"yyCache.memoryCache.totalCost:%lu",(unsigned long)yyCache.memoryCache.totalCost);
NSLog(@"yyCache.memoryCache.costLimit:%lu",(unsigned long)yyCache.memoryCache.costLimit);
NSLog(@"yyCache.memoryCache.totalCount:%lu",(unsigned long)yyCache.memoryCache.totalCount);
NSLog(@"yyCache.memoryCache.countLimit:%lu",(unsigned long)yyCache.memoryCache.countLimit);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(120 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"yyCache.diskCache.totalCost:%lu",(unsigned long)yyCache.diskCache.totalCost);
NSLog(@"yyCache.diskCache.costLimit:%lu",(unsigned long)yyCache.diskCache.costLimit);
NSLog(@"yyCache.diskCache.totalCount:%lu",(unsigned long)yyCache.diskCache.totalCount);
NSLog(@"yyCache.diskCache.countLimit:%lu",(unsigned long)yyCache.diskCache.countLimit);
for(int i=0 ;i<100;i++){
//模拟一个key
NSString *key=[NSString stringWithFormat:@"whoislcj%d",i];
id vuale=[yyCache objectForKey:key];
NSLog(@"key :%@ value : %@",key ,vuale);
}
});
YYCache和PINCache一样并没有实现基于最大内存开销进行LRU,不过YYCache实现了最大缓存数据个数进行LRU清理,这一点也是选择YYCache原因之一,对于YYCache磁盘LRU清理并不是及时清理,而是后台开启一个定时任务进行RLU清理操作,定时时间默认是60s。
YYCache与PINCache对比
对于我这里的使用场景大部分用于缓存json字符串,我这里就以存储字符串来对比一下写入与读取效率
1.写入性能对比
YYCache
//模拟数据
NSString *value=@"I want to know who is lcj ?";
//模拟一个key
NSString *key=@"key";
//YYCache
YYCache *yyCache=[YYCache cacheWithName:@"LCJCache"];
//写入数据
CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
[yyCache setObject:value forKey:key withBlock:^{
CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
NSLog(@" yyCache async setObject time cost: %0.5f", end - start);
}];
CFAbsoluteTime start1 = CFAbsoluteTimeGetCurrent();
[yyCache setObject:value forKey:key];
CFAbsoluteTime end1 = CFAbsoluteTimeGetCurrent();
NSLog(@" yyCache sync setObject time cost: %0.5f", end1 - start1);
运行结果
PINCache
//PINCache
//模拟数据
NSString *value=@"I want to know who is lcj ?";
//模拟一个key
NSString *key=@"key";
PINCache *pinCache=[PINCache sharedCache];
//写入数据
CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
[pinCache setObject:value forKey:key block:^(PINCache * _Nonnull cache, NSString * _Nonnull key, id _Nullable object) {
CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
NSLog(@" pincache async setObject time cost: %0.5f", end - start);
}];
CFAbsoluteTime start1 = CFAbsoluteTimeGetCurrent();
[pinCache setObject:value forKey:key];
CFAbsoluteTime end1 = CFAbsoluteTimeGetCurrent();
NSLog(@" pinCache sync setObject time cost: %0.5f", end1 - start1);
运行结果
通过上面的测试可以看出 同样大小的数据,无论同步方式还是异步方式,YYCache性能都要由于PINCache。
2.读取性能对比
YYCache
YYCache *yyCache=[YYCache cacheWithName:@"LCJCache"];
//模拟一个key
NSString *key=@"key";
CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
//读取数据
[yyCache objectForKey:key withBlock:^(NSString * _Nonnull key, id<NSCoding> _Nonnull object) {
CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
NSLog(@" yyCache async objectForKey time cost: %0.5f", end - start);
}];
CFAbsoluteTime start1 = CFAbsoluteTimeGetCurrent();
[yyCache objectForKey:key];
CFAbsoluteTime end1 = CFAbsoluteTimeGetCurrent();
NSLog(@" yyCache sync objectForKey time cost: %0.5f", end1 - start1);
运行结果:
PINCache
PINCache *pinCache=[PINCache sharedCache];
//模拟一个key
NSString *key=@"key";
CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
//读取数据
[pinCache objectForKey:key block:^(PINCache * _Nonnull cache, NSString * _Nonnull key, id _Nullable object) {
CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
NSLog(@" pincache async objectForKey time cost: %0.5f", end - start);
}] ;
CFAbsoluteTime start1 = CFAbsoluteTimeGetCurrent();
[pinCache objectForKey:key];
CFAbsoluteTime end1 = CFAbsoluteTimeGetCurrent();
NSLog(@" pinCache objectForKey time cost: %0.5f", end1 - start1);
运行结果:
通过运行结果,在读取方面YYCache也是优于PINCache。
总结:
经过一番查阅资料和自己写例子测试,最终项目中决定使用YYCache进行缓存管理。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# IOS
# YYCache
# IOS缓存管理
# 移除
# 的是
# 时就
# 开源
# 是否存在
# 实现了
# 链表
# 都要
# 大家都
# 的说
# 毫无用处
# 它是
# 要把
# 这两个
# 很简单
# 做个
# 这几天
# 可以看出
# 原因之一
# 来做
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel Eloquent模型如何创建_Laravel ORM基础之Model创建与使用教程
Laravel控制器是什么_Laravel MVC架构中Controller的作用与实践
Laravel怎么清理缓存_Laravel optimize clear命令详解
浅谈Javascript中的Label语句
Laravel路由Route怎么设置_Laravel基础路由定义与参数传递规则【详解】
青岛网站建设如何选择本地服务器?
laravel怎么通过契约(Contracts)编程_laravel契约(Contracts)编程方法
手机怎么制作网站教程步骤,手机怎么做自己的网页链接?
Laravel如何实现全文搜索_Laravel Scout集成Algolia或Meilisearch教程
如何在建站之星绑定自定义域名?
夸克浏览器网页跳转延迟怎么办 夸克浏览器跳转优化
HTML透明颜色代码怎么让图片透明_给img元素加透明色的技巧【方法】
Swift中switch语句区间和元组模式匹配
如何快速搭建高效WAP手机网站?
免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?
🚀拖拽式CMS建站能否实现高效与个性化并存?
Win11应用商店下载慢怎么办 Win11更改DNS提速下载【修复】
如何确认建站备案号应放置的具体位置?
Laravel如何使用Passport实现OAuth2?(完整配置步骤)
如何快速查询网站的真实建站时间?
韩国网站服务器搭建指南:VPS选购、域名解析与DNS配置推荐
齐河建站公司:营销型网站建设与SEO优化双核驱动策略
Laravel Seeder填充数据教程_Laravel模型工厂Factory使用
怎么制作网站设计模板图片,有电商商品详情页面的免费模板素材网站推荐吗?
香港服务器部署网站为何提示未备案?
企业在线网站设计制作流程,想建设一个属于自己的企业网站,该如何去做?
Laravel怎么在Blade中安全地输出原始HTML内容
北京网站制作公司哪家好一点,北京租房网站有哪些?
Laravel如何为API生成Swagger或OpenAPI文档
阿里云高弹*务器配置方案|支持分布式架构与多节点部署
Laravel如何配置任务调度?(Cron Job示例)
Laravel的契約(Contracts)是什么_深入理解Laravel Contracts与依赖倒置
Laravel集合Collection怎么用_Laravel集合常用函数详解
怎么用AI帮你设计一套个性化的手机App图标?
企业网站制作这些问题要关注
Laravel全局作用域是什么_Laravel Eloquent Global Scopes应用指南
使用豆包 AI 辅助进行简单网页 HTML 结构设计
如何基于云服务器快速搭建网站及云盘系统?
香港代理服务器配置指南:高匿IP选择、跨境加速与SEO优化技巧
Laravel如何使用Blade组件和插槽?(Component代码示例)
网站建设整体流程解析,建站其实很容易!
Laravel怎么配置S3云存储驱动_Laravel集成阿里云OSS或AWS S3存储桶【教程】
如何选择可靠的免备案建站服务器?
JavaScript实现Fly Bird小游戏
如何用VPS主机快速搭建个人网站?
中国移动官方网站首页入口 中国移动官网网页登录
Microsoft Edge如何解决网页加载问题 Edge浏览器加载问题修复
Laravel如何安装Breeze扩展包_Laravel用户注册登录功能快速实现【流程】
如何用IIS7快速搭建并优化网站站点?
黑客如何通过漏洞一步步攻陷网站服务器?

