2019年9月5日(木)~9月7日(土)にかけて開催された「iOSDC Japan 2019」において、サイバーエージェントはダイアモンドスポンサーを務め、5名が登壇しました。
本日は、「Ameba(アメーバ)」のiOSエンジニアの行木さん(@Ridwy )が発表した「カスタムInstrumentsでアプリをピカピカに!」のトークについて、同じく「Ameba(アメーバ)」のiOSエンジニアの仙石が解説します。
©︎ iOSDC Japan
Instrumentsについて
Instrumentsは、Xcodeに組み込まれている「実行時にさまざまな情報を収集し分析・可視化してくれるツール」です。アプリの動作やパフォーマンスを可視化することができて、デバックやパフォーマンス改善に役立ちます。
特に以下のケースでの使用が便利だと感じています。
-
ソースコードの問題を追跡
-
アプリのパフォーマンスの可視化
-
メモリーリークなどのアプリのメモリー問題の発見
基本的な使い方
XcodeでのInstrumentsの起動方法は2通りの方法があります。
-
単独での起動
-
アプリがセットされた状態での起動
「単独での起動」では、Xcode > Open Developer Tool > Instruments で起動することができます。また、Dockに表示されているXcodeのアイコンを右クリック > Open Developer Tool > Instrumentsからも起動することができます。
「アプリがセットされた状態での起動」では、Product > Profile (command + I)からアプリがセットされた状態でInstrumentsを起動することができます。
個人的には、開発中にはTransferでInstrumentsを立ち上げて、Time Profilerテンプレートでパフォーマンスの計測をすることが多いです 。アプリ実行後にデバッグナビゲーター > CPU > Profile in Instruments > Transferを選択することで、実行中のアプリにInstrumentsをAttachして実行することができるので、デバッグ中に気になったらすぐにInstrumentsを実行できます。
Instrumentsを起動することができたら、多くの計測用のテンプレートがあるので、用途に合わせてテンプレートの選択 > 計測したいデバイスとアプリを選択 > 赤丸の「Record」ボタンをクリックで計測を開始します。
上部の「Track Area」には時系列で計測結果がグラフで表示されます。
左下部の「Detail Area」には、「Track Area」で指定した範囲の計測結果の情報が表示されます。また、「Detail Area」では、結果をソートすることも可能です。
「Extended Detail Area」では、「Detail Area」で選択した行についてスタックトレースなどの詳細情報が表示されます。
個人的には、「Detail Area」の「Call Tree」と「メソッドジャンプ」の機能をよく使用しています。青色で囲まれているCall Treeをタップすると、チェックボックスが現れます。チェックボックの該当項目にチェックをつけることで表示されるデータをフィルターすることができます。例えば、「Hide System Function」にチェックをつけることで、アプリのコードのみが表示されます。
「メソッドジャンプ」は「Detail Area」に表示されているメソッドをダブルクリックすることで、Xcodeのエディタの該当のコードに遷移することができます。
Instrumentsのテンプレート
トークではInstrumentsの多くのテンプレートからいくつかが紹介されました。便利なテンプレートとしては
- Leaks
- Time Profiler
があります。
Leaksでは、メモリー使用量とリークの発生の有無が表示されます。リークを検知する間隔を変更することも可能です。メモリー使用量を確認することきには、スパイクが発生していないかを確認して、突発的なメモリー使用によるクラッシュ箇所を検知することができます。
Time Profilerでは、CPUのコアやThreadごとの使用率を可視化することができ、それらが効率よく使われているかを確認することができます。また、メソッドの処理時間や呼び出し回数を確認することができ、重たいメソッドを特定することもできます。
OSSignpostsについて
OSSignposts は iOS 12 で導入された計測に役立つマーカーです。実行タイミングを特定したいコードの箇所にos_signpostの処理を書いて、Instrumentsを実行することより、Instruments 上でグラフィカルに実行タイミングを表示することができます。
具体的には下記のように計測したい処理をos_signpostで囲みます。
import os.signpost
let logHandle = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "hoge")
let spid = OSSignpostID(log: logHandle)
os_signpost(.begin, log: logHandle, name: "Process A", signpostID: spid)
// Process A(計測対象の処理)
os_signpost(.end, log: logHandle, name: "Process A", signpostID: spid)
Instrumentのos_signpostで、結果を見ることができます。またcategoryに .pointsOfInterest を指定した場合は Points of Interest Instrumentにも表示されます。
Detail Areaでは、実行回数や平均の実行時間などが表示されるので処理のパフォーマンス計測がはかどります。
カスタムInstruments
Instrumentは自分で作成することも可能です。
カスタムInstrumentsを作成するにはまず、Xcode ->File -> New -> Project… で macOS タブの Instruments Packageを選んでプロジェクトを作成します。デフォルトで.instrpkgファイルが作られるので、そこにXMLで、Instrumentsに必要なModelerやスキーマを記述していきます。
配布するときには、Archiveを行い、生成された.instrdstを配布します。.instrdstをダブルクリックしてインストールすることで、作成したカスタムInstrumentsを使うことができます。
サンプルコード(Ridwy/iosdc19-custom-instruments)として2つのカスタムInstrumentsが用意されており参考になります。1つはos_signpostの内容をより見やすくし、アプリの状況を把握しやすくするもの、もう1つは後述するユーザーの行動ログの可視化とエラー検知を行うものです。
また、WWDC 2018 Creating Custom Instruments のセッションも参考になります。
プロダクトでのカスタムInstrumentsの活用事例として以下があります。
- API通信の可視化
- ユーザーの行動ログの実装確認
トークの最後にはカスタムModelerの作り方についても触れられました。Modelerの記述にはエキスパートシステムを作成するためのCLIPSという言語を使います。エキスパートシステムは専門家の判断能力をエミュレートするもので、発生したfact(事実)をルール(専門家の経験則など)に従って処理していきます。
例として、行動ログの実装ミスを検知する方法が提案されました。TapログのページIDが表示中の画面のページIDと異なってしまっていたら警告を出す、というルールをCLIPSで記述し、警告文がInstrumentsのDetail Areaに表示されるようになっていました。Instruments上で他の計測結果と一緒に、ログの実装ミスを検知できるのは便利だと思います。CLIPSを使うことでロジックを記述することができるので、Instrumentsの利用の幅が広がると思います。
まとめ
Instruments の基本的な使い方から始まり、OSSignpostsの使い方、カスタムInstrumentsの作成方法、活用事例、Modelerの記述方法までが紹介されました。アプリの状態を可視化することができるInstrumentsを積極的に使って、定期的にアプリの品質を向上できればと思います。
※ 使用画像はスライドから引用