こんにちは、iOSエンジニアのいっちー(@0IcchI)です。
ミラティブでは、iOS 18のリリースに備えて、アプリ上に新しい不具合が発生していないかの調査とその対応を進めてきました。
その過程でAnimated WebP
の再生に起因する致命的な不具合に出会ったので問題とその対応について紹介します。
背景
ミラティブではアプリ内で画像を表示する際にSDWebImageを使用しており、Animated WebP
の再生にも用いています。
SDWebImageはAnimated WebP
の再生に2種類のコーダーを提供しています。
SDImageAWebPCoder
- iOS標準の
ImageIO
フレームワークに含まれるコーダー
- iOS標準の
SDImageWebPCoder
- SDWebImage独自のコーダー
SDWebImageWebPCoder
のREADMEではそれぞれの違いについて以下のように記述されています。
AppleのImageIOはiOS 14、tvOS 14、watchOS 7、macOS 11以降でWebPのデコードをサポートしています。
そのため、これらのプラットフォーム上では、SDWebImageは組み込みのSDWebImageAWebPCoderを使用してWebP画像をデコードできます。
ただし、いくつかの制限がある可能性があり、詳細はSDWebImageのIssue #3558を確認してください。これらのプラットフォームでこのコーダーを強制的に使用することもできます。
引用:GitHub - SDWebImage/SDWebImageWebPCoder: A WebP coder plugin for SDWebImage, use libwebp
これまで、ミラティブでは iOS標準のImageIO
フレームワークに含まれるコーダーであるSDImageAWebPCoder
を使用してきました。
SDWebImageではSDImageCodersManager
に使用したいコーダーのインスタンスを渡すことで、以降の処理で画像の表示などにそのコーダーを利用することができます。
SDImageCodersManager.shared.addCoder(SDImageAWebPCoder.shared)
発生していた事象
iOS 18のベータ版を用いた検証により、Animated WebP
を再生する際に、以下のような深刻なパフォーマンス問題が確認されました。調査の中で、この問題はiOS 17では発生しておらず、iOS 18から発生する問題であることが分かりました。
事象1: Animated WebPの再生時にUIがフリーズする
不具合挙動ではUI描画が数秒間固まり、ユーザー操作が不能になっている。
事象2: Animated WebPの再生速度が極端に低下する
不具合挙動では正常な再生ができていない。
このようなパフォーマンスの問題は、ユーザー体験を大きく損なうため無視できるものではありませんでした。
問題の分析
Instruments
を用いて問題を分析した結果、次のことが分かりました。
ハングの検出
- 事象1発生時に5秒以上のハングを検出。
CPU使用率の上昇
- 両事象発生時にCPU使用率が異常に高くなることを確認。
さらにCPU使用率が上昇している箇所を詳しく分析したところ、Animated WebP
のデコード処理に多大な時間がかかっていることが分かりました。
これはImageIO
ライブラリ中の処理であることが分かります。
インターネット上で調査したところ、ImageIO
フレームワークではiOS 17以前においても、Animated WebP
のフレーム間の差分処理のパフォーマンスに問題がある可能性が指摘されていました(参考記事: Bandisoftの説明)。
これがiOS 18でより深刻化している可能性がありそうです。
対応方法
調査を進めた結果、SDWebImage独自コーダーを用いるSDWebImageWebPCoder
を利用すると、iOS 18においてもiOS 17以前と同等のパフォーマンスが出ることが分かりました。
SDImageCodersManager.shared.addCoder(SDImageWebPCoder.shared /* SDImageAWebPCoder.shared */)
上記の対応によって、iOS 18におけるAnimated WebP
の再生時のCPU使用率が改善し、ハングも発生しなくなりました。
補足
この問題の再現確認ができるようにiOS 17とiOS 18でのパフォーマンスを比較するプロジェクトを作成し、Appleに報告しています。
今後のiOSアップデートで改善されることを願います!