iOSの画像読み込み速度の最適化

FastImageCacheは、画像がよりスムーズにまでスライドするようにリストに基づいて、写真の負荷を持ち上げると速度をレンダリングするためのオープンソースのライブラリを開発し、それが行われたかを見てみましょうパスチームです。

まず、最適化のポイント

iOSのは、ディスクからイメージをロードし、使用UIImageVIewが画面に表示され、次の手順を実行する必要があります。

  1. カーネルバッファからデータをコピーするディスク
  2. ユーザ空間にカーネルバッファからデータをコピーします
  3. UIImageViewは、UIImageViewに割り当てられた画像データを生成しました
  4. 画像データは、PNG / JPG、デコードビットマップデータを復号されない場合
  5. ツリーの変更UIImageView層にCATransactionキャプチャ
  6. メインスレッド実行ループはCATransaction、画像の描画開始を提出します
    • データがバイト整列されていない場合には、Core Animationのは、データ・バイトが整列コピーします。
    • レンダリングされたビットマップデータを処理するGPU。

2,4,6 FastImageCacheは、(1)3つのステップを最適化しました。

  1. カーネル空間操作にユーザ空間からデータをコピーするために、上記ステップ2において省略MMAPメモリマップを使用。
  2. ディスクにデコードされたデータをバッファビットマップ、次のステップ4は、ディスク操作を読んだときに復号化を省略しています。
  3. レンダリングされたときに第6(1)ステップCoreAnimationを防止するために、生成されたバイト整列されたデータは、その後、データをコピーします。

次に、これら3点の詳細な説明、及びその実施を最適化します。

第二に、メモリマッピング

私たちは通常、ディスク上のファイルを読んで、最終的にデータを読み取るために、システムの読み取り()を使用しますメソッドに上位のAPIコールは、カーネルのディスクデータは、カーネルバッファに読み込まれ、その後、カーネルバッファメモリからユーザ空間にデータをコピーするようにユーザーを読みます、メモリコピー時間を消費するがあり、ファイル全体のデータを読み込んだ後、既に、ユーザメモリに存在するプロセスは、メモリ空間を占有します。

FastImageCacheは、ファイルを読み書きする別の方法を使用し、使用するユーザーの仮想メモリ空​​間へのmmapファイルをマッピングされている、仮想メモリアドレスに対応するファイルの場所ではなく、この文書のメモリ操作の動作と同じであってもよいですそれはメモリにファイル全体に置くが、物理メモリを消費しませんが、これらのデータを実際に使用する前に、ディスクの読み取りとだけは本当に画面上の画像をレンダリングする準備ができているデータを、使用時に書き込み操作は、できませんされています、仮想メモリ管理システムVMSは、欠落ページが物理メモリに対応するディスクのデータブロックからロードさに応じてローディング機構の前に、その後レンダリング。このようなファイルは、カーネルのキャッシュウェイに非常に効率的なファイルのコピーより少ないユーザ空間からデータを読み込み、書き込み。

第三に、デコードされた画像

我々は、ビットマップデータが画像ではなく、符号化データ圧縮の結果であり、一般的な画像は、JPG / PNGで使用し、復号されたビットマップデータをレンダリングするために必要とされるこの復号動作は、より多くの時間がかかり、前の画面に変換および復号ないGPUハードウェアは、CPUのみを介して、IOSのデフォルトは、メインスレッドで画像をデコードしません。多くの図書館は、画像を復号化する問題を解決してきたが、デコードされた画像が大きすぎると、一般的にディスクにキャッシュされていないため、時間のかかる操作をデコードするが本業ではないので、SDWebImageの練習では、メインスレッドから子スレッドの復号操作を移動することですタイムスレッド。

FastImageCache、サブスレッド復号画像において、それはデコードキャッシュ後にディスクにそのイメージを除きます。デコードされた画像の大容量ので、FastImageCacheの部分を達成するために、以下に詳述するように、画像データバッファ管理の一連からなります。さらに、キャッシュされた画像ボリュームではメモリマップドファイル、使用メモリマップドファイル決して小さな利点、少ないメモリコピーを読んで使用するための大きな理由は、ユーザメモリ占有のコピーは、より大きな、より大きなメモリマップファイルの利点、高いものではありません。

第四に、バイト整列

非バイト整列のケースをレンダリングする前に、画像データ中のCore Animationは、第1の画像データをコピーしますが、この動作をコピーするための公式文書が示されていない、シミュレータがあるとインストゥルメントは、「コピー画像」機能を強調したが、バグがコピーをレンダリングしたときにコールスタックから、強調表示されることが示されていない画像はまだCAは::レンダリング呼び出し:: COPY_IMAGEメソッドを参照することができたとしても、そこにあるようです。


それは私がそれを理解し、基礎となるのパフォーマンスのために画像を描画するピクセルレンダリングによってピクセルではなく、データをレンダリングするのピースが1枚ずつ撮影している、あなたは連続したメモリデータのこの部分が発生する可能性があり、そのバイトアライメントにどのようなものです最終的に画像データの内容ではない他のデータメモリであり、-国境を越えるためにつながる可能性がありそうCoreAnimationは、処理データのコピーを作成し、各部分が画像データであることを保証するために、ためにレンダリングする前に、中で混合し、いくつかの奇妙なことを読んでデータブランキングの欠如。それは一般的に示している:(画素が画像画素データであり、データは他のデータメモリです)


あなたは、画像データのアライメント64バイトのCoreAnimationを避けることができるように64バイトによってサイズがCPUのキャッシュラインに関連しなければならないブロック、のARMv7は32バイトで、A9は64バイトで、CoreAnimationでA9は、データをコピーし、へとレンダリングデータの一部として読まれるべきです修理。FastImageCache DOバイトアライメントはこの事です。

第五に、達成

FastImageCache同じタイプとサイズは、画像ファイルに格納され、ファイルに基づいて、撮影した単一の画像は、ウェブ状スプライト図CSSをオフセット、ImageTableと呼びます。これは、画像キャッシュ、キャッシュ制御FastImageCacheはImageTableの一つである全体のデータ管理のサイズの統合管理の便宜のために主にあります。図全体的なデータ構造を実装します:


そして、いくつかの追加説明:

5.1 ImageTable

ImageTable、ImageFormatにImageFormatの対応は、均一なサイズを提供ImageFormatて画像データに、画像レンダリングフォーマット/サイズ及び他の情報にImageTableをImageTableを指定し、各画像のサイズは同じです。

A ImageTable物理ファイルは、ファイルを保存して、このImageTableの別のメタ情報を持っています。

图像使用 entityUUID作为唯一标示符,由用户定义,通常是图像url的hash值。ImageTable Meta的indexMap记录了entityUUID->entryIndex的映射,通过indexMap就可以用图像的entityUUID找到缓存数据在ImageTable对应的位置。

5.2 ImageTableEntry

ImageTable的实体数据是ImageTableEntry,每个entry有两部分数据,一部分是对齐后的图像数据,另一部分是meta信息,meta保存这张图像的UUID和原图UUID,用于校验图像数据的正确性。

Entry数据是按内存分页大小对齐的,数据大小是内存分页大小的整数倍,这样可以保证虚拟内存缺页加载时使用最少的内存页加载一张图像。

图像数据做了字节对齐处理,CoreAnimation使用时无需再处理拷贝。具体做法是CGBitmapContextCreate创建位图画布时bytesPerRow参数传64倍数。

5.3 Chunk

ImageTable和实体数据Entry间多了层Chunk,Chunk是逻辑上的数据划分,N个Entry作为一个Chunk,内存映射mmap操作是以chunk为单位的,每一个chunk执行一次mmap把这个chunk的内容映射到虚拟内存。为什么要多一层chunk呢,按我的理解,这样做是为了灵活控制mmap的大小和调用次数,若对整个ImageTable执行mmap,载入虚拟内存的文件过大,若对每个Entry做mmap,调用次数会太多。

5.4 缓存管理

用户可以定义整个ImageTable里最大缓存的图像数量,在有新图像需要缓存时,如果缓存没有超过限制,会以chunk为单位扩展文件大小,顺序写下去。如果已超过最大缓存限制,会把最少使用的缓存替换掉,实现方法是每次使用图像都会把UUID插入到MRUEntries数组的开头,MRUEntries按最近使用顺序排列了图像UUID,数组里最后一个图像就是最少使用的。被替换掉的图片下次需要再使用时,再走一次取原图—解压—存储的流程。

六、使用

FastImageCache 适合用于 tableView 里缓存每个 cell 上同样规格的图像,优点是能极大加快第一次从磁盘加载这些图像的速度。但它有两个明显的缺点:

  1. 占空间大。因为缓存了解码后的位图到磁盘,位图是很大的,宽高 100*100 的图像在 2x 的高清屏设备下就需要 200*200*4byte/pixel = 156KB,这也是为什么 FastImageCache 要大费周章限制缓存大小。
  2. 接口不友好,需预定义好缓存的图像尺寸。FastImageCache 无法像 SDWebImage 那样无缝接入UIImageView,使用它需要配置 ImageTable,定义好尺寸,手动提供的原图,每种实体图像要定义一个 FICEntity 模型,使逻辑变复杂。

FastImageCache 已经属于极限优化,做图像加载/渲染优化时应该优先考虑一些低代价高回报的优化点,例如 CALayer 代替 UIImageVIew,减少 GPU 计算(去透明/像素对齐),图像子线程解码,避免 Offscreen-Render 等。在其他优化都做到位,图像的渲染还是有性能问题的前提下才考虑使用 FastImageCache 进一步提升首次加载的性能,不过字节对齐的优化倒是可以脱离 FastImageCache 直接运用在项目上,只需要在解码图像时 bitmap 画布的 bytesPerRow 设为 64 的倍数即可。

文章

iOS图片加载速度极限优化—FastImageCache解析

おすすめ

転載: www.cnblogs.com/dins/p/ios-tu-pian-jia-zai-su-du-you-hua.html