UI ジャンクの検出
コレクションでコンテンツを整理
必要に応じて、コンテンツの保存と分類を行います。
Android は、アプリからフレームを生成して画面に表示することで、UI をレンダリングします。アプリの UI レンダリングが遅いと、システムはフレームをスキップせざるを得なくなり、ユーザーは画面のちらつきを感じます。これを「ジャンク」といいます。
ジャンクが発生する場合、通常は、UI スレッド(ほとんどのアプリではメインスレッド)でなんらかの速度低下やブロッキング非同期呼び出しが発生したことが原因です。システム トレースを使用すると、問題のある場所を特定できます。
Android 12 以降でジャンクを検出する
Android 12(API レベル 31)以降を搭載したデバイスの場合、キャプチャされたトレースは CPU Profiler の [Display] ペインにある [Janky frames] トラックに表示されます。
ジャンクを検出する手順は次のとおりです。
Android Studio で、[View] > [Tool Windows] > [Profiler] を選択するか、ツールバーのプロファイル アイコン
をクリックします。
[Select Deployment Target] ダイアログが表示されたら、プロファイリング用にアプリをデプロイするデバイスを選択します。USB 経由でデバイスを接続しているにもかかわらずデバイスがリストに表示されない場合は、USB デバッグが有効になっているかを確認します。
CPU タイムラインの任意の場所をクリックして CPU Profiler を開きます。
CPU Profiler の構成メニューで [System Trace] を選択し、[Record] をクリックします。アプリの操作が完了したら、[Stop] をクリックします。
[Display] の下に [Janky frames] トラックが表示されます。デフォルトでは、Profiler は調査対象の候補としてジャンクのあるフレームのみを表示します。ジャンクのあるフレーム内で赤くハイライト表示された部分は、レンダリング期限からの超過時間を表しています。
![[Janky frames] トラックのスクリーンショット](https://developer.android.google.cn/static/studio/images/profile/jank_detection-janky_frames.png?hl=ja)
ジャンクのあるフレームが表示されたら、それをクリックします。M キーを押すと、選択したフレームを中心に表示倍率を調整できます。関連するイベントが、メインスレッド、[RenderThread]、[GPU completion] スレッドでハイライト表示されます。
![[Janky frames] とメインスレッドが表示された Profiler のスクリーンショット](https://developer.android.google.cn/static/studio/images/profile/jank_detection-janky_frames_detailed.png?hl=ja)
[All Frames]、[Lifecycle] のチェックボックスをオンにすることで、それぞれ、すべてのフレーム、レンダリング時間の内訳を表示できます。
![上と同じ Profiler 画面で [All Frames] と [Lifecycle] のチェックボックスをオンにした場合のスクリーンショット](https://developer.android.google.cn/static/studio/images/profile/jank_detection-allframes_lifecycle_checkboxed.png?hl=ja)
Android 11 でジャンクを検出する
Android 11(API レベル 30)搭載デバイスの場合、キャプチャされたトレースは CPU Profiler の [Frame Lifecycle] セクションに表示されます。
![さまざまなトラックが含まれる [Frame Lifecycle] セクション](https://developer.android.google.cn/static/studio/images/profile/jank_detection-frame-lifecycle-tracks.png?hl=ja)
[Frame Lifecycle] セクションには、レイヤ名と 4 つのトラックが表示されます。各トラックは、フレーム レンダリング パイプラインの 1 つのステージを表しています。Frame Lifecycle の要素は次のとおりです。
- Frame Lifecycle(レイヤ名): セクション タイトルとして、かっこ書きでレイヤ名が表示されます。レイヤは、単一の合成単位です。
- Application: このトラックは、アプリによってバッファがキューから除外されてから、再度キューに追加されるまでの時間を示します。これは通常、
RenderThread
のトレース イベントに対応します。
- Wait for GPU: このトラックは、GPU がバッファを保有していた期間を示します。これは、バッファが GPU に送信されてから、GPU がバッファに対する処理を終了するまでの時間です。GPU がこの期間にこのバッファのみを処理していたということではありません。特定の期間に GPU が処理していた内容の詳細な情報については、Android GPU Inspector を使用することをおすすめします。
- Composition: このトラックは、SurfaceFlinger がバッファをラッチして合成のために送信してから、バッファがディスプレイに送信されるまでの時間を示します。
- Frames on display: このトラックは、フレームが画面に表示されていた期間を示します。
[Frame Lifecycle] セクションは、フレーム バッファがレンダリング パイプラインのさまざまなステージ間をどのように移動するかを示します。フレームはフレーム番号ごとに色分けされているため、特定のフレームを簡単に追跡できます。
Android Studio では、トレース内のすべてのフレームを [All Frames] タブに表形式で表示することもできます。
![[All Frames] タブにおけるトレース内の全フレームの表](https://developer.android.google.cn/static/studio/images/profile/jd-all-frames.png?hl=ja)
[Frame #]、[Application]、[Wait for GPU]、[Composition] の各列には、上記の [Frame Lifecycle] セクション内のトラックと同じデータが表示されます。[Frame Duration] 列は、[Application] の開始から [Frames on Display] の開始までの時間を示します。これは基本的に、1 つのフレームをエンドツーエンドでレンダリングするためにかかる時間です。
フレームの表を任意の列で並べ替えると、最短または最長のフレームをすばやく見つけることができます。この表には、何百ものフレーム間を移動するのに役立つページネーション コントロールもあります。
Android 11 でジャンクを検出して調査する手順は次のとおりです。
[Application] 列を基準にして [All Frames] 表を降順に並べ替えて、最も時間がかかるフレームから表示されるようにします。
![降順に並べ替えられた [Application] 列](https://developer.android.google.cn/static/studio/images/profile/jank_detection-app-col-sorted.png?hl=ja)
最も時間がかかっているフレームを見つけて、表の行を選択します。左側のタイムライン ビューで選択したフレームにズームインします。
![タイムライン ビューと [Frames] 表](https://developer.android.google.cn/static/studio/images/profile/jank_detection-timeline-and-frames-table.png?hl=ja)
[Frame Lifecycle] セクションと [Threads] セクションで、関連するスレッドを探します。
![[Frame Lifecycle] セクションと [Threads] セクション](https://developer.android.google.cn/static/studio/images/profile/jank_detection-frame-lifecycle-threads.png?hl=ja)
Android 10 以前でジャンクを検出する
Android 10(API レベル 29)以前を搭載したデバイスの場合、関連する OS グラフィック パイプライン情報は、CPU Profiler システム トレースの [Display] という 1 つのセクションに表示されます。

- Frames: このセクションは、アプリの UI スレッドと
RenderThread
トレース イベントを示します。16 ミリ秒より長いイベントは赤色で示され、60 フレーム/秒(FPS)でレンダリングするための期限を超えることから、ジャンクが発生した可能性としてハイライト表示されます。
- SurfaceFlinger: このセクションは、SurfaceFlinger がフレーム バッファを処理するタイミングを示します。SurfaceFlinger は、表示するバッファの送信を行うシステム プロセスです。
- VSYNC: このセクションは、ディスプレイ パイプラインを同期する信号である VSYNC を示します。トラックには VSYNC-app シグナルが表示されます。これはアプリの起動が遅すぎることを示します。通常は、UI スレッドがビジー状態であることが原因です。これにより、アニメーション中に画面にちらつきが発生し、アニメーションまたはスクロールが完了するまでの入力レイテンシが増えます。1 秒あたり 60 回を超える頻度で、または変動レートで発生する可能性があるため、リフレッシュ レートの高いディスプレイでの表示には VSYNC が特に重要です。
- BufferQueue: このセクションは、キューに入れられ、SurfaceFlinger が使用するまで待機しているフレーム バッファの数を示します。Android 9(API レベル 28)以降を搭載しているデバイスにデプロイされたアプリの場合、このトラックにはアプリのサーフェス BufferQueue(
0
、1
、または 2
)のバッファ数が表示されます。BufferQueue は、Android グラフィック コンポーネント間を移動する際の画像バッファの状態を把握するのに役立ちます。たとえば値が 2
の場合は、アプリがトリプル バッファされていることを意味します。その結果、入力レイテンシが長くなります。
[Display] セクションでは、UI スレッドや RenderThread
に 16 ミリ秒以上かかった場合など、起こり得るジャンクを検出するために役立つシグナルを確認できます。ジャンクの原因の詳細を正確に調査するには、UI レンダリングに関連するスレッドが表示される [Threads] セクションを調べます。
![[Display] の [Threads] セクション](https://developer.android.google.cn/static/studio/images/profile/jank_detection-threads.png?hl=ja)
上の図では、[Threads] セクションに UI スレッド(java.com.google.samples.apps.iosched
)、RenderThread
、GPU completion
スレッドが表示されています。これらは UI レンダリングに関連するスレッドであり、ジャンクを引き起こす可能性があります。
Android 10 以前のデバイスでジャンクを検出する手順は次のとおりです。
[Display] の [Frames] トラックを確認します。赤いフレームは調査候補です。
![[Display] の [Frames] セクション](https://developer.android.google.cn/static/studio/images/profile/jank_detection-frames-track.png?hl=ja)
ジャンクのある可能性のあるフレームが見つかったら、Ctrl キー(macOS では Command キー)を押しながら、W
キーを押すかマウスホイールをスクロールしてズームインします。UI スレッドと RenderThread
のトレース イベントを確認できるようになるまでズームインし続けます。

上の図の Choreographer#doFrame
は、UI スレッドが Choreographer
を呼び出して、アニメーション、ビュー レイアウト、画像描画、関連プロセスを調整していたタイミングを示しています。DrawFrames
は、RenderThread
が形成され、実際の描画コマンドが GPU に発行されたタイミングを示しています。
特に長いトレース イベントがあれば、さらにズームインして、レンダリングが遅くなった原因を確認できます。上の図は、UI スレッドの inflate
を示しています。これは、アプリがレイアウトのインフレートに時間を費やしていることを意味します。inflate
イベントのいずれかにズームインすると、下の図に示すように、各 UI コンポーネントにかかっている時間を正確に確認できます。

詳細
ジャンクを減らす方法については、一般的なジャンク発生源をご覧ください。
このページのコンテンツやコードサンプルは、コンテンツ ライセンスに記載のライセンスに従います。Java および OpenJDK は Oracle および関連会社の商標または登録商標です。
最終更新日 2025-07-27 UTC。
[null,null,["最終更新日 2025-07-27 UTC。"],[],[],null,["# UI jank detection\n\nAndroid renders UI by generating a frame from your app and displaying it on\nthe screen. If your app suffers from slow UI rendering, then the system is\nforced to skip frames. When this happens, the user perceives a recurring flicker\non their screen, which is referred to as *jank*.\n\nWhen jank occurs, it's usually because of some deceleration or blocking async\ncall on the UI thread (in most apps, it's the main thread). You can use system\ntraces to identify where the problem is.\n\nDetect jank on Android 12 and higher\n------------------------------------\n\nFor devices using Android 12 (API level 31) or higher, a captured trace is shown\nin the **Janky frames** track under the **Display** pane in the CPU Profiler.\n\nTo detect jank,\n\n1. In Android Studio, select **View \\\u003e Tool Windows \\\u003e Profiler** or click **Profile**\n in the toolbar.\n\n If prompted by the **Select Deployment Target** dialog, choose the device to\n which to deploy your app for profiling. If you've connected a device over USB\n but don't see it listed, ensure that you have\n [enabled USB debugging](/studio/debug/dev-options#enable).\n2. Click anywhere in the **CPU** timeline to open the CPU Profiler.\n\n3. Select **System Trace** from the configurations menu in the CPU Profiler and\n click **Record** . After you finish interacting with your app, click **Stop**.\n\n4. You should see the **Janky frames** track under **Display** . By default, the\n Profiler only shows janky frames as candidates for investigation. Within each\n janky frame, the red portion highlights the duration the frame takes past its\n rendering deadline.\n\n5. Once you find a janky frame, click on it; optionally, you can press **M** to\n adjust the zoom to focus on the selected frame. The relevant events are\n highlighted in these threads: the main thread, **RenderThread** and\n **GPU completion** .\n\n6. You can optionally see all frames or a breakdown of the rendering time by\n toggling the checkboxes **All Frames** and **Lifecycle** , respectively.\n\nDetect jank on Android 11\n-------------------------\n\nFor devices using Android 11 (API level 30), a captured trace is shown in the\n**Frame Lifecycle** section in the CPU Profiler.\n\nThe **Frame Lifecycle** section contains the layer name and four tracks. Each\ntrack represents one stage in the frame rendering pipeline. The **Frame\nLifecycle** elements are as follows:\n\n1. **Frame Lifecycle (Layer name)** : The section title contains the layer name in parentheses. A *layer* is a single unit of composition.\n2. **Application** : This track shows the time from when the buffer was dequeued by the app to when it was enqueued back. This usually corresponds to the trace events in `RenderThread`.\n3. **Wait for GPU** : This track shows how long the buffer was owned by the GPU. This is the time from when the buffer is sent to the GPU to when the GPU finishes its work on the buffer. **This does not indicate that the GPU was working only on\n this buffer during this time.** For detailed info on what the GPU works on during a given time, you may want to use [Android GPU Inspector](/agi).\n4. **Composition**: This track shows the time starting from when SurfaceFlinger latches on to the buffer and sends it for composition, to when the buffer is sent to the display.\n5. **Frames on display**: This track shows how long the frame was on the screen.\n\nThe **Frame Lifecycle** section illustrates how a frame buffer moves between\ndifferent stages of the rendering pipeline. The frames are color coded by frame\nnumber so that it's easier to track a particular frame.\n\nAndroid Studio also shows all frames in the trace in a table format in the **All\nFrames** tab.\n\nThe **Frame #** , **Application** , **Wait for GPU** , and\n**Composition** columns represent the same data as the tracks in the **Frame\nLifecycle** section as above. The column **Frame Duration** represents the time\nfrom the start of **Application** to the start of **Frames on Display**. This is\nessentially how long it takes to render a frame end-to-end.\n\nYou can sort the frames table by any column to quickly find the shortest or\nlongest frame. The table also supports pagination controls that help you navigate\nthrough hundreds of frames.\n\nTo detect and investigate jank on Android 11, follow these steps:\n\n1. Sort the **All Frames** table by the **Application** column in descending\n order, so that the frames that take the longest appear first.\n\n2. Find the longest running frames and select the table row. This zooms in on\n the selected frame in the timeline view to the left.\n\n3. Look for relevant threads in the **Frame Lifecycle** and **Threads** sections.\n\nDetect jank on Android 10 and lower\n-----------------------------------\n\nFor devices using Android 10 (API level 29) and lower, relevant OS graphics\npipeline information is displayed in a single section on the CPU Profiler system\ntrace called **Display**.\n\n- **Frames** : This section shows the UI thread and `RenderThread` trace events in your app. Events that are longer than 16ms are colored red to highlight potential janky frames because they exceed the deadline to render at 60 frames per second (fps).\n- **SurfaceFlinger**: This section shows when the SurfaceFlinger processes the frame buffers. SurfaceFlinger is a system process that is responsible for sending buffers to display.\n- **VSYNC**: This section displays the VSYNC, a signal that synchronizes the display pipeline. The track displays the VSYNC-app signal, which shows when your app is starting too late. Typically, this occurs because the UI thread is busy. It causes a visible flicker to appear on your screen during an animation and adds extra input latency until the animation or scroll completes. This is especially important to view for high-refresh-rate displays, as they may occur more frequently than 60 times per second or at a variable rate.\n- **BufferQueue** : This section shows how many frame buffers are queued up and are waiting for SurfaceFlinger to consume. For apps deployed to devices running Android 9 (API level 28) or higher, this track shows the buffer count of the app's surface [BufferQueue](https://source.android.com/devices/graphics#bufferqueue) (`0`, `1`, or `2`). BufferQueue can help you understand the state of image buffers as they move between the Android graphics components. For example, a value of `2` means that the app is currently triple-buffered, which results in extra input latency.\n\nThe **Display** section provides useful signals to detect potential jank---for\nexample, when the UI thread or `RenderThread` takes longer than 16 ms. To investigate\nexact details of what caused the jank, you can probe the **Threads**\nsection, which shows the threads relevant to UI rendering.\n\nIn the figure above, the **Threads** section shows the UI thread\n(`java.com.google.samples.apps.iosched`), `RenderThread`, and the `GPU completion`\nthread. These are the threads relevant to UI rendering and may contribute to\njank.\n\nTo detect jank on Android 10 or lower, follow these steps:\n\n1. Look at the **Frames** track in **Display**. The red frames are candidates\n for investigation.\n\n2. Once you find a potentially janky frame, zoom in by pressing `W` or\n scrolling the mouse wheel while holding \u003ckbd\u003eControl\u003c/kbd\u003e\n (\u003ckbd\u003eCommand\u003c/kbd\u003e on macOS). Continue zooming in until you start to see the\n trace events in the UI thread and `RenderThread`.\n\n In the figure above, `Choreographer#doFrame` shows when the UI thread calls\n [`Choreographer`](/reference/android/view/Choreographer) to coordinate\n animation, view layout, image drawing, and related processes. `DrawFrames`\n shows when `RenderThread` forms and issues actual drawing commands to the GPU.\n3. If you see a particularly long trace event, you can zoom in further and find out\n what may have contributed to the slow rendering. The figure above shows `inflate`\n in the UI thread, which means the app is spending time on inflating the layout.\n When you zoom into one of the `inflate` events, you can find out exactly how long\n each UI component is taking, as shown below.\n\nLearn more\n----------\n\nTo learn more about how to reduce jank, see\n[Common sources of jank](/topic/performance/vitals/render#common-jank)."]]