你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> iOS圖片緩存庫基准對比

iOS圖片緩存庫基准對比

編輯:IOS開發基礎

023.jpg

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

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

為了獲得良好的用戶體驗,當我們緩存和加載圖像時,了解iOS底層如何處理是很重要的。此外,大多數使用了圖片緩存的開源庫也是個不錯解決方案。

2.常用的解決途徑

  • 異步下載圖像

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

  • 寫入磁盤

  • 需要時從磁盤讀取並展示 

// 假設我們有一個 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;
        });
    }];
}

FPS 簡介

  • UI渲染理想情況FPS=60

  •  60FPS => 16.7ms 每幀 這就意味著 如果任何主線程操作大於16.7ms,動態FPS將會下降,因為cpu忙於處理其他事情 而不是渲染UI。

3.常用解決途徑的缺點

  • 從磁盤加載圖像或文件時間消耗昂貴(磁盤讀取比內存讀取慢大概10 - 1000倍,如果是SSD硬盤 可能與內存讀取速度更接近(大概慢10倍)。參考這裡的比較:Introduction to RAM Disks。如果使用SSD,將獲得接近內存的速度(大概比內存訪問速度慢十倍),但目前還沒有手機和平板集成SSD模塊。

  • 創建UIImage實例將會在內存區生成一個圖片的壓縮版。但是壓縮後的圖像太小且無法渲染,如果我們從磁盤加載圖像,圖像甚至都沒有加載到內存。解壓圖片同樣也很消耗資源。

  • 設置imageView的image屬性,這種情況下將會創建一個CATransaction並加入主循環中。在下一次循環迭代中,CATransaction會對任何設置為layer contents的圖像進行拷貝。

拷貝圖像包含以下過程:

  • 給文件io 和 解壓縮 分配緩沖區

  • 讀取磁盤數據到內存

  • 解壓圖像數據(生成原位圖) - 高cpu消耗

  • CoreAnimation 使用解壓數據並渲染

字節位沒有正確對齊的圖像將被CoreAnimation拷貝,以修復字節位對齊並使之能被渲染。這一點在Apple 文檔裡沒有說明,但是使用Instruments表明 CA::Render::copy_image會執行此操作,即使Core Aniation 即使沒有拷貝圖像。

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

4.一個強大的iOS圖像緩存需包含以下部分: 

  • 異步下載圖像,盡可能減少使用主線程隊列。

  • 使用後台隊列解壓圖像。這是個復雜的過程,請閱讀Avoiding Image Decompression Sickness(http://www.cocoanetics.com/2011/10/avoiding-image-decompression-sickness/)。

  • 在內存和磁盤上緩存圖像。在磁盤上緩存圖像很重要,因為app可能因為內存不足而被強行關閉或者需要清理內存。這種情況下,重新從磁盤加載圖像比下載會快很多。備注:如果使用NSCache作為內存緩存,當有內存警告時,NSCache會清空緩存內容。NSCache相關細節請查看nshipster 上這篇文章:NSCache

  • 保存解壓過的圖片到硬盤以及內存中,以避免再次解壓。

  • 使用GCD 和 blocks,這將使得代碼更加高效和簡單。如今GCD 和 blocks是異步操作時必需的。

  • 最好使用UIImageView的分類以便集成

  • 最好在下載後以及存入到緩存前能夠處理圖像

iOS圖像優化 

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

Core Data 是一個好的選擇嗎?

這有一篇文章--CoreData 對比File System,實現圖像緩存的基准測試。結果File System的表現更好(正如我們所預期的)

看一看上面羅列的觀點,自己實現圖像緩存不僅復雜,耗時而且痛苦。這也是為什麼我傾向於使用開源的圖像緩存解決方案。你們大部分已經聽說過SDWebImage或new FastImageCache。

為了讓你知道哪個開源庫最適合你,我做了測試並且分析它們如何滿足上述要求。

5.基准測試

測試庫:

  • 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後在磁盤緩存方面出色的表現(基於NSURLCache實現)

測試場景

對於每個庫,我都會使用全新的測試app,然後啟動app,等所有圖像加載完後,慢慢滑動。然後以不同力度來回滑動(從慢到快)。接著關掉app強制應用從磁盤緩存中加載圖像,最後重復以上測試場景。

關於測試app工程

-相關demo可以在Github找到並獲取,名字是ImageCachingBenchmark。同時還有本次實驗的圖表、結果數據表以及更多。

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

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

最快與最慢的設備對比結果

在Github工程上能看到完整的基准測試結果,由於這些表格很大,我只使用運行最快的設備iPhone 5s和運行最慢的iPhone 4來測試。

001.jpg


002.jpg


003.jpg


004.jpg

匯總:

74.jpg

表格名詞解釋

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

-後台解壓 =通過後台隊列或線程執行圖像解壓

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

-內存/磁盤緩存 = 支持內存/磁盤緩存

-UIImageView分類 = 庫中含UIImageView 類別

-從內存/磁盤 = 從緩存(內存/磁盤)中讀取的平均時間

6.結論

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

-SDWebImage 和 AFNetworking 是穩定的工程。由於有很多貢獻者,這樣保證代碼能夠及時得到維護。FastImageCache在維護方面更新很快。

-基於以上所有數據,我認為SDWebImage 在目前是一個很好的解決方案。即使有些工程使用AFNetworking 或 FastImageCache更好。但是這些都依賴於項目需求。

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved