Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
FtnApp 的缩略图实践
Search
Frank Xu
August 26, 2012
Programming
110
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
FtnApp 的缩略图实践
Frank Xu
August 26, 2012
More Decks by Frank Xu
See All by Frank Xu
Proxy Pattern
yyfrankyy
0
110
微信读书阅读器架构
yyfrankyy
2
2.3k
Watcher - EventBus Reinvented
yyfrankyy
0
180
SQLite 调优实践
yyfrankyy
0
200
JSDoc 的使用
yyfrankyy
0
200
交易平台化(前端)
yyfrankyy
0
230
淘宝搜索前端优化
yyfrankyy
0
250
淘宝排行榜 V3 项目总结
yyfrankyy
0
180
Other Decks in Programming
See All in Programming
ゲームコントローラやキーボードのファームウェアをSwiftで書く
kishikawakatsumi
1
250
大喜利で理解するLLM as a Judge / Understanding LLM-as-a-Judge through Ogiri
rockname
0
150
UnityでSystem.Net.WebSocketsなWebSocketサーバが動かないのでUnity Monoのコードを覗いてみた / about implementing websocket server with unity mono
drumath2237
1
260
iOSDC2026登壇資料.pdf
riofujimon
0
170
WebMCP Challenge に星空観察アプリで参加した話
okajun35
0
190
新卒PdEのリアル
ryu1013
1
510
一人だけ、Kiroが静止する日
hideg
0
120
技術的負債を組織課題として解く-増えすぎたマイクロサービスとの戦い-
reimaru
1
2.2k
Building an Out-of-Order CPU
latte72
1
790
AHC070解法紹介
eijirou
0
130
動作中のプログラムの中身をリアルタイムに覗く / Realtime Debugger for CSharp with Roslyn
prota
1
810
モバイル交通系ICへのチャージ実例から考える、クロスプラットフォーム開発におけるiOS実機テスト設計とCI運用
yusuga
1
520
Featured
See All Featured
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Between Models and Reality
mayunak
4
460
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.8k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
280
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
68
57k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.6k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
3k
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
710
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.4k
Chasing Engaging Ingredients in Design
codingconduct
0
320
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
470
Reflections from 52 weeks, 52 projects
jeffersonlam
356
21k
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