iOS
計測器によるプロファイル
サーチ…
前書き
Xcodeには、Instrumentsという名前のパフォーマンスチューニングアプリケーションが含まれています。このアプリケーションを使用すると、あらゆる種類の異なるメトリックを使用してアプリケーションをプロファイルできます。 CPU使用率、メモリ使用量、リーク、ファイル/ネットワークアクティビティ、およびエネルギー使用量を調べるツールがあります。 Xcodeからアプリのプロファイリングを開始するのは簡単ですが、プロファイリング時に見えるものを理解するのが簡単ではない場合があります。このため、一部の開発者はこのツールを最大限に活用できなくなります。
タイムプロファイラ
あなたが見る最初の計測器はTime Profiler
です。計測された間隔で、Instrumentsはプログラムの実行を停止し、実行中の各スレッドでスタックトレースを取得します。 Xcodeのデバッガで一時停止ボタンを押していると考えてください。タイムプロファイラのスニークプレビューは次のとおりです。
この画面には、 Call Tree
表示されます。 Call Tree
は、アプリ内のさまざまなメソッドで実行に費やされた時間が表示されます。各行は、プログラムの実行パスに従った別の方法です。各メソッドで費やされた時間は、各メソッドでプロファイラが停止した回数から判断できます。たとえば、 100個のサンプルが1ミリ秒の間隔で実行され、特定のメソッドが10個のサンプルのスタックの先頭にあると判明した場合、実行時間の10ミリ秒 - 約10%が費やされたと推測できますその方法で。それはかなり粗雑な近似ですが、それは動作します!
Xcode's
メニューバーからProduct\Profile
選択するか、 press ⌘I
。これでアプリが構築され、Instrumentsが起動されます。次のような選択ウィンドウが表示されます。
これらはすべて、インストゥルメントに付属する異なるテンプレートです。
Time Profiler
計測器を選択し、「選択」をクリックします。これにより、新しいInstruments文書が開きます。録画を開始してアプリを起動するには、左上の赤い録音ボタンをクリックします 。他のプロセスを分析するためにインストゥルメントに権限を与えるためにパスワードを要求されることがあります - 恐れていないので、ここで提供するのが安全です! インストゥルメントウィンドウでは、時間のカウントアップ、画面の中央のグラフの上から左に向かって小さな矢印が表示されます。これは、アプリが実行中であることを示します。
さて、アプリの使用を開始します。いくつかの画像を検索し、1つまたは複数の検索結果にドリルダウンします。おそらく、検索結果に入るのが面倒なことに気づいたことがあります。また、検索結果のリストをスクロールすることも非常に面倒です - それは非常にclunkyアプリです!
まあ、運が良かったんだよ、それを修正しようとしているから!しかし、あなたはまずインストゥルメントであなたが見ているものをすばやく見つけようとしています。まず、ツールバーの右側にあるビューセレクタに、次のように両方のオプションが選択されていることを確認します。
これにより、すべてのパネルが確実に開かれます。以下のスクリーンショットと、その下の各セクションの説明を調べてください。
1.これらは録音コントロールです。赤色の「レコード」ボタンは、クリックされたときに現在プロファイルされているアプリケーションを停止&開始します(レコードと停止アイコンの間で切り替えます)。一時停止ボタンは、アプリの現在の実行を予期し、一時停止します。
2.これは実行タイマーです。タイマーは、プロファイリングされているアプリケーションの実行時間と、実行された回数をカウントします。レコーディングコントロールを使用してアプリケーションを停止して再起動すると、新しい実行が開始され、ディスプレイにRun 2 of 2が表示されます。
3.これは、トラックと呼ばれています。選択したタイムプロファイラテンプレートの場合、1つの楽器しかないので、1つのトラックしかありません。このチュートリアルの後半にあるグラフの詳細については、こちらをご覧ください。
4.詳細パネルです。あなたが使用している特定の楽器に関する主な情報を表示します。この場合、最もホットな方法、つまり最もCPU時間を使い果たした方法を示しています。 Call Tree(左手のもの)と表示されている上部のバーをクリックしてSample Listを選択すると、データの別のビューが表示されます。このビューはすべての単一のサンプルを表示しています。いくつかのサンプルをクリックすると、キャプチャされたスタックトレースがExtended Detailインスペクタに表示されます。
5.これはインスペクタパネルです。レコード設定、表示設定、拡張詳細の3つのインスペクタがあります。まもなくこれらのオプションのいくつかについてもっと学びます。
深い掘削
イメージ検索を実行し、結果をドリルダウンします。私は個人的には「犬」を検索するのが好きですが、何でも好きなものを選んでください。あなたはその猫の一人かもしれません!
今度は、リストを数回上下にスクロールして、 Time Profiler
で十分な量のデータを取得してください。画面の中央にある数字が変わり、 グラフが塗りつぶされます。これは、 CPU サイクルが使用されていることを示しています。
あなたは実際には、これはtable view
がバターのようにスクロールするまで出荷する準備ができているので、これは本当にどんなUIも見苦しいとは思わないでしょう!問題を特定するために、いくつかのオプションを設定する必要があります。
右側で、 Display Settingsインスペクタを選択します(or press ⌘+2)
ます(or press ⌘+2)
。 インスペクタの [ Call Tree
セクションで、[ スレッドで区切る]、[ Call Tree
反転する]、[欠落しているシンボルを隠す]、および[システムライブラリを隠す]を選択します。それは次のようになります:
左側の表に表示されているデータに対して、各オプションが何をしているかを示します。
個別スレッド:各スレッドは別々に検討する必要があります。これにより、どのスレッドがCPU使用量の最大の原因であるかを理解することができます。
Invert Call Tree:このオプションを使用すると、 stack trace
は上から下にとらえられstack trace
。これは通常、 CPUが時間を費やしている最も深い方法を見たいので、あなたが望むものです。
不足しているシンボルを隠す: dSYM
ファイルがアプリケーションまたはsystem framework
で見つからない場合は、テーブル内のメソッド名(シンボル)を表示する代わりに、バイナリ内のアドレスに対応する16進値が表示されます。このオプションを選択すると、完全に解決されたシンボルのみが表示され、未解決の16進値は非表示になります。これは提示されたデータを明確にするのに役立ちます。
Hide System Libraries:このオプションを選択すると、自分のアプリからのシンボルだけが表示されます。通常、このオプションを選択すると便利です。通常は、 CPUが自分のコードで時間を費やす場所だけを気にします。 system libraries
が使用しているCPUの量はあまり多くありません。
Flatten Recursion:このオプションは、複数の関数ではなく、各stack trace
1つのエントリとして再帰関数(それ自身を呼び出す関数)を扱います。
Top Functions:この機能を有効にすると、 Instruments
は関数内で費やされた合計時間を、その関数内で直接的に発生した時間と、その関数によって呼び出された関数で費やされた時間の合計とみなします。
したがって、関数AがBを呼び出すと、Aの時間は、Aで費やされた時間がBで費やされた時間として報告されます。これは、コールスタックに降下するたびに最大の時間フィギュアを選ぶことができるので、あなたの最も時間のかかる方法で。
Objective-C
アプリケーションを実行している場合は、Show Obj-C Onlyのオプションもあります。これを選択すると、 C
またはC++
関数ではなくObjective-C
メソッドだけが表示されます。あなたのプログラムには何もありませんが、もしあなたがOpenGL
アプリを見ていれば、例えばC++
持っているかもしれません。
上記のオプションを有効にした場合、いくつかの値が若干異なる場合がありますが、エントリの順序は以下の表と似ているはずです。
まあ、それは確かにあまりにも良く見えません。大部分の時間はサムネイル写真に「色調」フィルタを適用する方法に費やされます。表の読み込みとスクロールがUIのもっとも重要な部分であったため、表のセルが絶えず更新されているので、それはあまりにも衝撃的ではありません。
そのメソッド内で何が起こっているのかを調べるには、テーブルの行をダブルクリックします。これを行うと、次のビューが表示されます。
それは面白いですね。 applyTonalFilter()
は拡張UIImage
に追加されたメソッドであり、イメージフィルタを適用した後にCGImage出力を作成するのに費やされる時間はほぼ100 %です。
これをスピードアップするためにできることはあまりありません。イメージを作成するにはかなりの時間がかかります。一applyTonalFilter()
踏み込んで、 applyTonalFilter()
がどこから呼び出されたかを見てみましょう。前の画面に戻るには、コードビューの上部にあるブレッドクラムのトレイルで[ Call Tree
をクリックします。
次に、テーブルの上部にあるapplyTonalFilter行の左側にある小さな矢印をクリックします。これにより、呼び出しツリーが開き、applyTonalFilterの呼び出し元が表示されます。次の行も展開する必要があります。 Swiftのプロファイリング時に、@ objcの接頭辞を持つ呼び出しツリーに重複した行があることがあります。アプリケーションのターゲット名のプレフィックスが付いた最初の行に興味があります(InstrumentsTutorial):
この場合、この行は結果コレクションビューのcellForItemAtIndexPath
ます。行をダブルクリックすると、プロジェクトから関連するコードが表示されます。
今、あなたは問題が何かを見ることができます。トーンフィルタを適用するメソッドは実行に時間がかかり、cellForItemAtIndexPathから直接呼び出されます。これは、フィルタリングされた画像を要求するたびにmain thread
(したがってUI全体)をブロックしmain thread
。
割り当て
作成されているすべてのオブジェクトとそのオブジェクトをバックアップするメモリに関する詳細情報があります。各オブジェクトのretain counts
をretain counts
ていることも示しています。新しいinstruments profile
で新たに開始するには、計測器アプリを終了します。今回は、アプリケーションをビルドして実行し、ナビゲータ領域でデバッグナビゲータを開きます。 [ メモリ ]をクリックすると、メインウィンドウにメモリ使用量のグラフが表示されます。
これらのグラフは、アプリの実績を簡単に把握するのに便利です。しかし、もう少し力が必要です。 [ Profile in Instruments
]ボタンをクリックし、[Transfer]をクリックして、このセッションをInstrumentsに持ち込みます。 Allocations計測器が自動的に起動します。
今回は2つのトラックに気づくでしょう。 1つは割り当てと呼ばれ、1つはリークと呼ばれます。 Allocationsトラックについては後で詳しく説明します。 Leaksのトラックは一般にObjective-Cでより便利です。このチュートリアルではカバーされません。だから、あなたは次にどんなバグを見つけようとしていますか?あなたがおそらくそこにいるか分からないプロジェクトに隠された何かがあります。あなたはおそらくメモリリークについて聞いたことがあります。しかし、実際には2種類のリークがあることが分かりません。
真のメモリリークは、オブジェクトがもはや何かによって参照されなくても、まだ割り当てられていることです。つまり、メモリは決して再利用できません。 SwiftとARC
がメモリを管理するのに役立つ場合でも、メモリリークの最も一般的な種類はretain cycle or strong reference cycle
です。これは、2つのオブジェクトが互いに強い参照を保持しているため、各オブジェクトが他のオブジェクトの割り当てを解除しないようにするためです。これは彼らの記憶が決して解放されないことを意味します!
無制限のメモリの増加は、メモリの割り当てが継続され、割り当てが解除されることはありません。これが永遠に続くと、ある時点でsystem's memory
がいっぱいになり、手に大きなメモリ問題が発生します。 iOSでは、これはアプリがシステムによって殺されることを意味します。
Allocations 計測器をアプリで実行すると、アプリ内で5つの異なる検索を行いますが、まだ結果にドリルダウンしません。検索結果に結果があることを確認してください!今、アプリを数秒待って少し落ち着かせましょう。
Allocationsトラックのグラフが上昇していることに注目したはずです。これは、メモリが割り当てられていることを示しています。 unbounded memory growth
を見いだすためにあなたを導くこの機能です。
あなたが実行しようとしているのはgeneration analysis
です。これを行うには、マーク生成と呼ばれるボタンを押します。ディスプレイ設定インスペクタの上部にボタンがあります:
それを押すと、トラックに赤い旗が表示されます。
generation analysis
の目的は、アクションを複数回実行して、メモリがunbounded fashion
増加しているかどうかを確認することです。検索にドリルダウンし、イメージが読み込まれるまで数秒待ってから、メインページに戻ります。その後、世代を再度マークします。異なる検索に対してこれを繰り返します。いくつかの検索にドリルダウンした後、 Instrumentsは次のようになります。
この時点で、あなたは疑わしいものになっているはずです。 ドリルダウンする各検索で青色のグラフがどのように表示されるかに注目してください。まあ、それは確かに良くありません。しかし、 memory warnings?
あなたはそれらについて知っていますよね? Memory warnings
は、メモリ部門で状況が厳しくなっていることをアプリに伝えるためのiOSの方法です。メモリをクリアする必要があります。
この成長は単にあなたのアプリによるものではない可能性があります。それはメモリに保持されているUIKit
の深みにあるものかもしれません。いずれかの指を指す前に、システムフレームワークとアプリにメモリをクリアするチャンスを与えます。
シミュレートmemory warning
選択することで、 Instrument\Simulate Memory Warning
Instrumentsのメニューバー、またはでHardware\Simulate Memory Warning
からsimulator's
メニューバーを。メモリ使用量が少し減っているか、まったく変わっていないかもしれません。確かにどこに戻らないのか。だからどこかで起こっている無限の記憶の成長はまだあります。
検索にドリルする各繰り返しの後に生成をマークする理由は、各世代間にどのメモリが割り当てられているかを見ることができるためです。ディテールパネルを見てみると、たくさんの世代が見えます。