畫面播放速率

平均每秒影格數

流暢穩定的影格率是 Android 裝置提供優質遊戲體驗的關鍵。評估遊戲效能時,您應將平均 FPS 視為基準,藉此初步瞭解遊戲體驗。請將遊戲最佳化,達到平均每秒 60 個影格率,確保玩家享有優質遊戲體驗。

P90 和 P99 FPS (穩定性)

即使遊戲的平均影格速率達到流暢的 60 FPS,仍可能發生間歇性延遲、微頓挫和無法預測的輸入延遲,導致玩家體驗不佳。

因此,影格穩定性與追蹤平均影格率同樣重要。您應在此處分別測量 P90 和 P99 影格率指標,做為一致的基準和延遲指標。這些指標會擷取效能的「尾端」,協助您提升玩家體驗的流暢度。

指標

  • 平均 FPS (基準):這項基本指標可提供遊戲效能的一般基準。雖然這是標準基準,但平均計算方式表示系統無法偵測到間歇性影格掉格和微頓挫,因此單獨使用這項指標不足以代表玩家體驗。
  • P90 FPS (第 10 個百分位數的穩定基準):這表示有 90% 的影格超過這個穩定基準,只有最慢的 10% 影格需要較長時間才能顯示。如果 P90 影格率很高且接近平均值,表示遊戲在大部分工作階段中都能穩定運作。
  • P99 FPS (第 1 個百分位數的頓挫指標):這表示有 99% 的影格超過這個頓挫指標,特別是速度最慢的 1% 影格。這項指標對於偵測微幅頓挫、資產載入延遲,以及導致明顯頓挫的資產密集型算繪尖峰至關重要。

範例

比較平均 FPS 與 P90 和 P99 指標,即可準確診斷遊戲的基礎行為。

情境 1:最佳曲線 (已最佳化的遊戲)

  • 平均:60 FPS (16.6 毫秒)
  • P90:58 FPS (17.2 毫秒)
  • P99:52 FPS (19.2 毫秒)
  • 分析:指標緊密聚集。遊戲體驗非常流暢穩定。不會出現微小頓挫,即使是品質最差的 1% 影格,人類肉眼也幾乎無法察覺。

情境 2:負載瓶頸 (CPU/GPU 繫結)

  • 平均:45 FPS (22.2 毫秒)
  • P90:40 FPS (25.0 毫秒)
  • P99:38 FPS (26.3 毫秒)
  • 分析:平均影格率較低,但穩定性高。與平均值相比,P99 並未大幅下降。這表示系統基本上是因圖像設定或解析度限制而負荷過重。遊戲不會有延遲感,但會感覺遲緩。降低圖像設定通常會使這些指標一致向上調整。

情境 3:60 FPS 不穩定 (著色器編譯 / 資產串流 卡頓)

  • 平均:60 FPS (16.6 毫秒)
  • P90:45 FPS (22.2 毫秒)
  • P99:15 FPS (66.6 毫秒)
  • 分析:這是最糟糕的情況。雖然平均影格率看起來很出色,但 P99 揭露了重大問題。P99 為 66.6 毫秒,表示遊戲一次凍結多個影格。這表示有嚴重離群值,通常是由 CPU 瓶頸、資產串流延遲 (例如 RAM 或儲存空間速度緩慢),或是著色器編譯造成的延遲所致。

評估

如要有效評估平均 FPS、P90 和 P99 FPS,可以使用下列兩種方法。第一種方法是使用 Android Performance Analyzer (APA) (效能剖析工具) 分析系統追蹤記錄。第二種方法是使用現有的 adb dumpsys SurfaceFlinger --timestats 指令。

1. 使用 APA 評估

您可以使用 APA 記錄系統追蹤記錄,並透過 SQL 查詢精確分析影格資料。請按照下列步驟評估指標:

  1. 使用 APA 擷取追蹤記錄:執行遊戲,並在要分析的區段 (例如遊戲中疑似影格掉落的點) 使用 APA 擷取系統追蹤記錄。裝置連線並完成追蹤記錄後,追蹤資料就會載入 APA 介面。

    追蹤擷取畫面或載入的追蹤畫面
  2. 在 APA 中點選「SQL」分頁:開啟追蹤分析畫面後,點選 UI 頂端或側邊導覽區域中的「SQL」分頁,即可開啟追蹤處理器環境,直接查詢資料。

  3. 將 SQL 查詢貼到 APA SQL 分頁中:複製下列 SQL 查詢,然後貼到查詢輸入欄位。這項查詢會找出 SurfaceFlinger 程序、根據實際螢幕更新時間戳記計算影格間隔,並推導出平均 FPS、最低 10% (P90) FPS 和最低 1% (P99) FPS。

    WITH target_process AS (
    -- 1. Get SurfaceFlinger process ID where frames were identified in debugging step 3
    SELECT upid
    FROM process
    WHERE name = '/system/bin/surfaceflinger'
    ),
    actual_present_times AS (
    -- 2. Calculate the hardware display timestamps when SurfaceFlinger actually updated the screen
    SELECT
        (ts + dur) AS present_ts
    FROM actual_frame_timeline_slice
    WHERE upid IN (SELECT upid FROM target_process)
        AND dur > 0
    ),
    present_intervals AS (
    -- 3. Calculate intervals between physical screen refreshes
    SELECT
        (LEAD(present_ts) OVER (ORDER BY present_ts ASC) - present_ts) / 1000000.0 AS p2p_ms
    FROM actual_present_times
    ),
    valid_intervals AS (
    -- 4. Filter for valid frame intervals
    SELECT p2p_ms
    FROM present_intervals
    WHERE p2p_ms IS NOT NULL AND p2p_ms > 0
    ),
    ordered_frames AS (
    -- 5. Sort in ascending order to calculate percentiles
    SELECT
        p2p_ms,
        ROW_NUMBER() OVER (ORDER BY p2p_ms ASC) AS row_num,
        COUNT(1) OVER () AS total_frames
    FROM valid_intervals
    )
    -- 6. Output final metrics
    SELECT
    (SELECT COUNT(1) FROM valid_intervals) AS total_presented_frames,
    ROUND(1000.0 / NULLIF((SELECT AVG(p2p_ms) FROM valid_intervals), 0), 2) AS average_fps,
    ROUND(1000.0 / NULLIF((SELECT p2p_ms FROM ordered_frames WHERE row_num = CAST(total_frames * 0.90 AS INT)), 0), 2) AS low_10_fps,
    ROUND(1000.0 / NULLIF((SELECT p2p_ms FROM ordered_frames WHERE row_num = CAST(total_frames * 0.99 AS INT)), 0), 2) AS low_1_fps;
    
  4. 按一下「執行查詢」:按一下查詢輸入欄位附近的「執行查詢」按鈕 (或執行圖示)。查詢執行完畢後,結果窗格的表格會顯示測得的總影格數 (total_presented_frames)、平均影格率 (average_fps)、最低 10% 的 FPS (low_10_fps) 和最低 1% 的 FPS (low_1_fps)。

    螢幕畫面:顯示已執行的 SQL 查詢,以及表格中顯示的四項指標

2. 使用 adb (dumpsys SurfaceFlinger) 測量

如要有效評估平均 FPS、P90 和 P99,可以使用 Android dumpsys surfaceflinger timestats 指令。這項工具會提供平均 FPS,以及所有正在算繪圖層的 presentToPresent 時間直方圖。影格的 presentToPresent 時間是指目前影格與上一個繪製影格之間的時間間隔。

以下是收集及計算遊戲指標的逐步說明:

  1. 開始擷取:執行下列指令,並使用 enable 和 clear 旗標開始擷取資訊:

    adb shell dumpsys SurfaceFlinger --timestats -clear -enable
    
  2. 傾印資訊:遊戲執行一段時間後,請再次執行指令並加上傾印標記,輸出資訊:

    adb shell dumpsys SurfaceFlinger --timestats -dump
    
  3. 依圖層篩選:傾印的資訊會提供 SurfaceFlinger 算繪的所有圖層資料。您必須根據 layerName 篩選,找出與遊戲對應的部分 (例如 layerName = SurfaceView[com.example.yourgame...])。

    layerName = SurfaceView[com.google.test/com.devrel.MainActivity]@0(BLAST)#132833
    
  4. 找出平均 FPS:系統會自動計算每個圖層的平均 FPS,並直接顯示在傾印輸出內容中 (例如 averageFPS = 30.179)。

    ...
    averageFPS = 30.179
    ...
    
  5. 計算 P90 和 P99 FPS:如要找出 P90 和 P99 指標,您需要分析傾印中提供的 totalFrames 和 presentToPresent 時間直方圖。

    totalFrames = 1000
    ...
    presentToPresent histogram is as below:
    0ms=0 1ms=0 2ms=0 3ms=0 4ms=0 5ms=0 6ms=0 7ms=0 8ms=0 9ms=0 10ms=0 11ms=0 12ms=0
    13ms=0 14ms=0 15ms=0 16ms=850 17ms=0 18ms=0 19ms=0 20ms=0 21ms=0 22ms=0 23ms=0
    24ms=0 25ms=0 26ms=0 27ms=0 28ms=0 29ms=0 30ms=0 31ms=0 32ms=0 33ms=100 34ms=0
    36ms=0 38ms=0 40ms=0 42ms=0 44ms=0 46ms=0 48ms=0 50ms=35 54ms=0 58ms=0 62ms=0
    66ms=10 70ms=0 74ms=0 78ms=0 82ms=0 86ms=0 90ms=0 94ms=0 98ms=0 102ms=5 106ms=0
    110ms=0 114ms=0 118ms=0 122ms=0 126ms=0 130ms=0 134ms=0 138ms=0 142ms=0 146ms=0
    150ms=0 200ms=0 250ms=0 300ms=0 350ms=0 400ms=0 450ms=0 500ms=0 550ms=0 600ms=0
    650ms=0 700ms=0 750ms=0 800ms=0 850ms=0 900ms=0 950ms=0 1000ms=0
    

    A. 概念範例 (累積分佈表) 假設遊戲工作階段記錄的 totalFrames 計數為 1,000。如要找出 P90 和 P99,請計算累積影格數分別達到 900 個影格 (90%) 和 990 個影格 (99%) 時的毫秒門檻,並從最低毫秒值開始計算。

    影格時間 (毫秒) 影格數 (直方圖) 累計影格數 百分位數狀態 / 計算
    16 毫秒 850 850 85.0%
    33 毫秒 100 950 95.0%
    (已達到 P90 目標 900!→ 1000/33 = 30.3 FPS)
    50 毫秒 35 985 98.5%
    66 毫秒 10 995 99.5%
    (已達到 P99 目標 990!→ 1000/66 = 15.1 FPS)
    102 毫秒 5 1,000 100%

    B. 實作邏輯 (虛擬程式碼) 如果您使用 Python 指令碼或記錄剖析器自動執行這項分析,可以按照下列方式實作邏輯,從直方圖中擷取 P90 和 P99 值:

    # Define target thresholds based on total frame count
    p90_target = totalFrames * 0.90
    p99_target = totalFrames * 0.99
    
    cumulative_frames = 0
    p90_fps = None
    p99_fps = None
    
    # Iterate through the parsed SurfaceFlinger histogram data (sorted by millisecond)
    for ms_bucket, frame_count in present_to_present_histogram:
        cumulative_frames += frame_count
    
        # Capture P90 when cumulative frames cross the 90% threshold
        if p90_fps is None and cumulative_frames >= p90_target:
            p90_fps = 1000 / ms_bucket
    
        # Capture P99 when cumulative frames cross the 99% threshold
        if p99_fps is None and cumulative_frames >= p99_target:
            p99_fps = 1000 / ms_bucket
            break # Optimization: stop iterating once both targets are found
    
  6. 停止擷取:收集所有必要資訊後,您應使用停用標記停用時間統計資料:

    adb shell dumpsys SurfaceFlinger --timestats -disable
    

緩慢工作階段

緩慢工作階段可找出普遍的實際效能問題。如果超過 25% 的影格低於門檻 (例如 20 FPS),工作階段就會被視為「緩慢」。雖然這項指標有助於找出重大建構問題,但單靠這項指標無法確保提供高品質的持續體驗。遊戲可能會避開緩慢工作階段門檻,但仍會出現微頓,導致無法提供流暢的 60 FPS 體驗。

雖然「緩慢工作階段」和「影格速率」都是從影格時間衍生而來,但兩者扮演的角色不同。平均、P90 和 P99 FPS 指標可衡量效能的品質和穩定性,偵測緩慢工作階段指標可能忽略的瞬間下降和不一致的步調。

結論

如要成功最佳化效能,必須採取全面策略。開發人員應將「緩慢工作階段」做為主要雷達,偵測效能嚴重下降的情況,然後檢查平均 FPS、P90 和 P99,診斷根本原因並驗證實際遊戲流暢度。整合這些指標後,即可確保應用程式提供持續穩定且出色的使用者體驗。

其他資源

如要進一步瞭解進階剖析技術、如何導入 Frame Pacing API,以及引擎專屬最佳化策略,請參閱 Android 開發人員官方說明文件:

  • Android Vitals:緩慢工作階段:瞭解 Google Play 如何評估及回報持續的轉譯速度緩慢,這會直接影響使用者體驗。「緩慢工作階段」是指緩慢影格占比超過 25% 的使用者工作階段 (例如超過 50 毫秒,相當於 20 FPS)。
  • Android 開發人員:最佳化遊戲效能:探索 Android 遊戲最佳化的中心樞紐。這份綜合指南涵蓋最佳做法、剖析工具 (例如 APAPerfetto),可協助您盡量提升遊戲的整體效能。