Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
FtnApp 的缩略图实践
Search
Frank Xu
August 26, 2012
Programming
0
47
FtnApp 的缩略图实践
Frank Xu
August 26, 2012
Tweet
Share
More Decks by Frank Xu
See All by Frank Xu
Proxy Pattern
yyfrankyy
0
79
微信读书阅读器架构
yyfrankyy
2
2.1k
Watcher - EventBus Reinvented
yyfrankyy
0
150
SQLite 调优实践
yyfrankyy
0
120
JSDoc 的使用
yyfrankyy
0
130
交易平台化(前端)
yyfrankyy
0
160
淘宝搜索前端优化
yyfrankyy
0
150
淘宝排行榜 V3 项目总结
yyfrankyy
0
110
Other Decks in Programming
See All in Programming
短期間での新規プロダクト開発における「コスパの良い」Goのテスト戦略」 / kamakura.go
n3xem
2
170
선언형 UI에서의 상태관리
l2hyunwoo
0
180
今年一番支援させていただいたのは認証系サービスでした
satoshi256kbyte
1
260
Stackless и stackful? Корутины и асинхронность в Go
lamodatech
0
830
Security_for_introducing_eBPF
kentatada
0
110
「Chatwork」Android版アプリを 支える単体テストの現在
okuzawats
0
180
開発者とQAの越境で自動テストが増える開発プロセスを実現する
92thunder
1
190
PHPで作るWebSocketサーバー ~リアクティブなアプリケーションを知るために~ / WebSocket Server in PHP - To know reactive applications
seike460
PRO
2
510
テストケースの名前はどうつけるべきか?
orgachem
PRO
0
140
fs2-io を試してたらバグを見つけて直した話
chencmd
0
240
StarlingMonkeyを触ってみた話 - 2024冬
syumai
3
270
Androidアプリのモジュール分割における:x:commonを考える
okuzawats
1
140
Featured
See All Featured
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
29k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.3k
Bash Introduction
62gerente
608
210k
Rails Girls Zürich Keynote
gr2m
94
13k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
10
810
Fashionably flexible responsive web design (full day workshop)
malarkey
405
66k
Raft: Consensus for Rubyists
vanstee
137
6.7k
Gamification - CAS2011
davidbonilla
80
5.1k
Why Our Code Smells
bkeepers
PRO
335
57k
A designer walks into a library…
pauljervisheath
204
24k
Writing Fast Ruby
sferik
628
61k
Building a Modern Day E-commerce SEO Strategy
aleyda
38
7k
Transcript
FtnApp 的缩略图实践 AyangXu
列表缩略图和预览大图 图片缓存策略(磁盘,内存) 耗时操作的应对(读写、压缩) 大图滑动的逐步调优 Agenda
两种缩略图的异同
列表缩略图 文件小(15-20k) 文件多(列表) 滑动的时候频繁读 高缓存命中
预览大图 文件大(200k+) 绘制耗时长 重用率低 内存控制要求更高
共同特点 平滑性要求高 多重检查:本地 ➜ 原图(压缩) ➜ 网络 过度状态(ICON / loadingView)
small loadThumbnail big QMCache thumb.db file original file web thumbnail
小图的缓存策略(磁盘) small loadThumbnail QMCache thumb.db original file web thumbnail
小图的缓存策略(磁盘) 全部小图保存到⼀一个 DB 启动的时候子线程加载(15k*100张) 滚动停止时,只更新 visibleCells 先更新内存,显示,再在后面更新 DB 不要在 cellForRowAtIndexPath
里做太多事情
图片缓存策略
小图的缓存策略(内存) 内存更新策略 缩略图只加不减 全部小图,包括默认的 ICON 都只读⼀一次
大图的缓存策略(内存) NSCache NSDiscardableContent / NSPurgeableData 不Copy Key,释放时机不可控 QMCache NSMutableArray w/
NSMutableDictionary 自定义 Capacity,多了就删
耗时操作的应对
QMCache thumb.db file original file web thumbnail 难点: 两种 IO
操作 两个网络操作 相互嵌套 本地 ➜ 原图 ➜ 网络
GCD VS OperationQueue GCD 保留作用域,线程池 不好控制并发任务,不好取消 NSOperationQueue w/ NSBlockOperation FIFO,封装了
GCD,可配置并发数,支持取消 保留还在队列里的 URL,避免重复的操作 快速滑动时,取消未开始的任务,优先留给当前页
[queue addOperation: [NSBlockOperation blockOperationWithBlock:^{ dispatch_async( dispatch_get_main_queue(), ^{/*UI*/}); }]]; dispatch_async( dispatch_get_global_queue(0,0),
^{ dispatch_async( dispatch_get_main_queue(),^{/*UI*/}); }); VS
大图滑动的逐步调优
大图滑动的基本实现
两层UIScrollView 1 2
⼀一次性准备ContentSize { numOfImages * (width + padding), height }
[previewImage renderMultipleImages: ^(int page, downloadImageCallback callback) { asyncLoadImage(page, ^(UIImage *image)
{ callback(image); }); } ]; 将读取逻辑扩展出去
评估工具 Core Animations Allocations Instruments
大图滑动 V1 图片和 loadingView 分开两个数组 未渲染部分用 [NSNull null] 占位,提前创建 好N个
loadingView 检查是否 [NSNull class] 来判定是否需要加 载 scrollViewDidEndDecelerating 时加载 每次加载时创建 view,加载过的不会释放
大图滑动 V1 FPS 10-15 不断创建新的 view,不断释放 在 scrollViewDidEndDecelerating 才加载,太 慢
进列表时间很长,初始化东西太多
大图滑动 V1.1 动态补充 loadingView 将绘制逻辑改到 scrollViewWillBeginDragging 缓存第二层的 zoomingScrollView
大图滑动 V1.1 进列表时间有所改善 所有第⼀一次翻动都很卡 FPS: 10-15 Cache 过的 view 不需重新创建
FPS: 20-30
大图滑动 V1.2 提前加载左右 N 页 判定是否到了 N 页,再进行加载 N =
5
大图滑动 V1.2 预加载左右 5 张,进列表时间又长了⼀一点 左右 5 张之内 FPS 30-40
第 6 张⼀一次性又要加载5张 FPS 10-20
大图滑动 V1.x zoomingScrollView 基本不可重用 大图缓存的命中率很低 每⼀一次绘制都需要遍历三个N长数组 图片,loadingView,zoomingScrollView 每次翻动的时间跟列表长度相关 O(N) 创建后不移出
view,subviews 越来越多
大图滑动 V2 不采用单独的 loadingView 数组和 [NSNull null] 用 zoomingScrollView 来引用
loadingView 跟 image View的缓存和回收 NSMutableSet 无序,NSObject 不重复 visiblePages / recyclePages
大图滑动 V2 scrollViewDidScroll 判定当前可见的页(<=2) 如果需要绘制,从 recyclePages 里 dequeue ⼀一个放到 visiblePages
回收不可见的页,从 visiblePages 里挪到 recyclePages 如果不需要绘制,什么都不做
大图滑动 V2 FPS 40-50 保持外层 UIScrollView 的 subviews,最多只 有两个 减少不断创建新
view 的开销 减少 scrollViewDidScroll 时的遍历开销 O(1)
进化路线 滑动时的 FPS 15 => 45 滑动时的遍历:O(n) => O(1) 内存增长:
view 的创建和回收: N => 2
Next? 大图内存没有尽快释放 [obj release] 只是引用-1,并没有马上释放 采用小图策略,DB 保存等比小图 ⼀一次加载到内存,内存只缓存小图 (20k *
100) 快速滑动时拉伸小图,模糊,但是快 scrollViewDidEndDecelerating 时绘制大图 view 不可见时马上清大图 image = nil;
And.. [NSURLConnection sendSynchronousRequest:returningResponse:error:] 所有网络数据都 load 到内存,并发下载三个, 内存涨了 10M (Oh my!)
对可能的大图片,异步 IO + 文件流
Thanks Q&A