iOS圖片緩存庫基準(zhǔn)對比

原文:iOS image caching. Libraries benchmark (SDWebImage vs FastImageCache),譯者夜微眠(github地址),校對藍(lán)魂(博客)、Cocoa(博客)。

1.引言

過去的幾年里,iOS應(yīng)用在視覺方面越來越吸引人。圖像展示是其中很關(guān)鍵的部分,因?yàn)榇蟛糠謭D像展示都需要下載并且渲染。大部分開發(fā)者都要使用圖像填充表格視圖(table views) 或者 集合視圖(collection views) 。下載圖片消耗一些資源(如蜂窩數(shù)據(jù)、電池以及CPU 等)。為了減少資源消耗,一些緩存模型也應(yīng)運(yùn)而生。

為了獲得良好的用戶體驗(yàn),當(dāng)我們緩存和加載圖像時(shí),了解iOS底層如何處理是很重要的。此外,大多數(shù)使用了圖片緩存的開源庫也是個(gè)不錯(cuò)解決方案。

2.常用的解決途徑

  • 異步下載圖像

  • 處理圖像(拉伸,去紅眼,去邊框)以便展示

  • 寫入磁盤

  • 需要時(shí)從磁盤讀取并展示
    <pre><code>
    // 假設(shè)我們有一個(gè) NSURL *imageUrl and UIImageView *imageView, 我們需要通過NSURL下載圖片并在UIImageview上展示
    if ([self hasImageDataForURL:imageUrl] {
    NSData *data = [self imageDataForUrl:imageUrl];
    UIImage *image = [UIImage imageWithData:imageData];
    dispatch_async(dispatch_get_main_queue(), ^{
    imageView.image = image;
    });
    } else {
    [self downloadImageFromURL:imageUrl withCompletion:^(NSData *imageData, …) {
    [self storeImageData:imageData …];
    UIImage *image = [UIImage imageWithData:imageData];
    dispatch_async(dispatch_get_main_queue(), ^{
    imageView.image = image;
    });
    }];
    }
    </pre></code>
    FPS 簡介

  • UI渲染理想情況FPS=60

  • 60FPS => 16.7ms 每幀 這就意味著 如果任何主線程操作大于16.7ms,動態(tài)FPS將會下降,因?yàn)閏pu忙于處理其他事情 而不是渲染UI。

3.常用解決途徑的缺點(diǎn)

  • 從磁盤加載圖像或文件時(shí)間消耗昂貴(磁盤讀取比內(nèi)存讀取慢大概10 - 1000倍,如果是SSD硬盤 可能與內(nèi)存讀取速度更接近(大概慢10倍)。參考這里的比較:Introduction to RAM Disks。如果使用SSD,將獲得接近內(nèi)存的速度(大概比內(nèi)存訪問速度慢十倍),但目前還沒有手機(jī)和平板集成SSD模塊。
  • 創(chuàng)建UIImage實(shí)例將會在內(nèi)存區(qū)生成一個(gè)圖片的壓縮版。但是壓縮后的圖像太小且無法渲染,如果我們從磁盤加載圖像,圖像甚至都沒有加載到內(nèi)存。解壓圖片同樣也很消耗資源。
  • 設(shè)置imageView的image屬性,這種情況下將會創(chuàng)建一個(gè)CATransaction并加入主循環(huán)中。在下一次循環(huán)迭代中,CATransaction會對任何設(shè)置為layer contents的圖像進(jìn)行拷貝。

拷貝圖像包含以下過程:

  • 給文件io 和 解壓縮 分配緩沖區(qū)
  • 讀取磁盤數(shù)據(jù)到內(nèi)存
  • 解壓圖像數(shù)據(jù)(生成原位圖) - 高cpu消耗
  • CoreAnimation 使用解壓數(shù)據(jù)并渲染

字節(jié)位沒有正確對齊的圖像將被CoreAnimation拷貝,以修復(fù)字節(jié)位對齊并使之能被渲染。這一點(diǎn)在Apple 文檔里沒有說明,但是使用Instruments表明 CA::Render::copy_image會執(zhí)行此操作,即使Core Aniation 即使沒有拷貝圖像。

從iOS7 開始,第三方應(yīng)用不能使用JPEG硬件解碼器。這意味著我們只能使用慢很多的軟解碼器。這一點(diǎn)在FastImageCache團(tuán)隊(duì)的 GitHub主頁以及 Nick Lockwood的推文上都有指出。

4.一個(gè)強(qiáng)大的iOS圖像緩存需包含以下部分:

  • 異步下載圖像,盡可能減少使用主線程隊(duì)列。
  • 使用后臺隊(duì)列解壓圖像。這是個(gè)復(fù)雜的過程,請閱讀Avoiding Image Decompression Sickness(http://www.cocoanetics.com/2011/10/avoiding-image-decompression-sickness/)。
  • 在內(nèi)存和磁盤上緩存圖像。在磁盤上緩存圖像很重要,因?yàn)閍pp可能因?yàn)閮?nèi)存不足而被強(qiáng)行關(guān)閉或者需要清理內(nèi)存。這種情況下,重新
  • 從磁盤加載圖像比下載會快很多。備注:如果使用NSCache作為內(nèi)存緩存,當(dāng)有內(nèi)存警告時(shí),NSCache會清空緩存內(nèi)容。NSCache相關(guān)細(xì)節(jié)請查看nshipster 上這篇文章:NSCache
  • 保存解壓過的圖片到硬盤以及內(nèi)存中,以避免再次解壓。
  • 使用GCD 和 blocks,這將使得代碼更加高效和簡單。如今GCD 和 blocks是異步操作時(shí)必需的。
  • 最好使用UIImageView的分類以便集成
  • 最好在下載后以及存入到緩存前能夠處理圖像

iOS圖像優(yōu)化

更多的成像相關(guān)以及SDK框架(CoreGraphics,ImageIO,CoreAnimation,CoreImage)工作原理,CPU vs GPU 等,請閱讀@rsebbe的文章:Advanced Imaging on iOS

Core Data 是一個(gè)好的選擇嗎?

這有一篇文章--CoreData 對比File System,實(shí)現(xiàn)圖像緩存的基準(zhǔn)測試。結(jié)果File System的表現(xiàn)更好(正如我們所預(yù)期的)

看一看上面羅列的觀點(diǎn),自己實(shí)現(xiàn)圖像緩存不僅復(fù)雜,耗時(shí)而且痛苦。這也是為什么我傾向于使用開源的圖像緩存解決方案。你們大部分已經(jīng)聽說過SDWebImage或new FastImageCache。

為了讓你知道哪個(gè)開源庫最適合你,我做了測試并且分析它們?nèi)绾螡M足上述要求。

5.基準(zhǔn)測試

測試庫:

  • SDWebImage - version 3.5.4
  • FastImageCache - version 1.2
  • AFNetworking - version 2.2.1
  • TMCache - version 1.2.0
  • Haneke - version 0.0.5

注:AFNetworking 加入對比是由于其自iOS7后在磁盤緩存方面出色的表現(xiàn)(基于NSURLCache實(shí)現(xiàn))

測試場景

對于每個(gè)庫,我都會使用全新的測試app,然后啟動app,等所有圖像加載完后,慢慢滑動。然后以不同力度來回滑動(從慢到快)。接著關(guān)掉app強(qiáng)制應(yīng)用從磁盤緩存中加載圖像,最后重復(fù)以上測試場景。

關(guān)于測試app工程

-相關(guān)demo可以在Github找到并獲取,名字是ImageCachingBenchmark。同時(shí)還有本次實(shí)驗(yàn)的圖表、結(jié)果數(shù)據(jù)表以及更多。

-請注意,請注意Github上的工程和圖像緩存庫都需要做一些調(diào)整,以便能讓我們看到每一張緩存的圖片都能夠被加載出來。由于我不想檢查Cocoapods源碼文件(不是個(gè)好習(xí)慣),所以需要對Cocoapods clean后重新編譯工程代碼 。目前Github上的版本與我做測試的版本有些差別。

-如果你們想重新跑一下測試,你需要編寫相同completionBlock用于圖像加載,所有庫得要跟默認(rèn)的SDWebImage一樣返回SDImageCacheType。

最快與最慢的設(shè)備對比結(jié)果

在Github工程上能看到完整的基準(zhǔn)測試結(jié)果,由于這些表格很大,我只使用運(yùn)行最快的設(shè)備iPhone 5s和運(yùn)行最慢的iPhone 4來測試。

匯總:

表格名詞解釋

  • 異步下載 = 庫支持異步下載

-后臺解壓 =通過后臺隊(duì)列或線程執(zhí)行圖像解壓

-存儲解壓 = 存儲解壓后的圖像版本

-內(nèi)存/磁盤緩存 = 支持內(nèi)存/磁盤緩存

-UIImageView分類 = 庫中含UIImageView 類別

-從內(nèi)存/磁盤 = 從緩存(內(nèi)存/磁盤)中讀取的平均時(shí)間

6.結(jié)論

-從頭開始編寫iOS圖像緩存組件很困難

-SDWebImage 和 AFNetworking 是穩(wěn)定的工程。由于有很多貢獻(xiàn)者,這樣保證代碼能夠及時(shí)得到維護(hù)。FastImageCache在維護(hù)方面更新很快。

-基于以上所有數(shù)據(jù),我認(rèn)為SDWebImage 在目前是一個(gè)很好的解決方案。即使有些工程使用AFNetworking 或 FastImageCache更好。但是這些都依賴于項(xiàng)目需求。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容