อัตราเฟรม

FPS เฉลี่ย

อัตราเฟรมที่ราบรื่นและเสถียรเป็นสิ่งสำคัญในการมอบประสบการณ์การเล่นเกมคุณภาพสูงในอุปกรณ์ Android เมื่อวัดประสิทธิภาพของเกม คุณควรวัด FPS เฉลี่ยเป็นพื้นฐานเพื่อให้เข้าใจประสบการณ์ขั้นพื้นฐาน คุณควรเพิ่มประสิทธิภาพเกมเพื่อให้มีอัตราเฟรมเฉลี่ย 60 FPS เพื่อให้มั่นใจว่าจะได้รับประสบการณ์การเล่นเกมที่ยอดเยี่ยม

FPS ที่ P90 และ P99 เพื่อความเสถียร

แม้จะมีค่าเฉลี่ย 60 FPS ที่ราบรื่น แต่เกมก็อาจยังคงประสบปัญหาการกระตุกเป็นระยะๆ การกระตุกเล็กๆ น้อยๆ และความหน่วงของอินพุตที่คาดเดาไม่ได้ ซึ่งส่งผลให้ผู้เล่นได้รับประสบการณ์ที่ไม่ดี

ดังนั้นความเสถียรของเฟรมจึงมีความสำคัญไม่แพ้การติดตามอัตราเฟรมเฉลี่ย ในส่วนนี้ คุณควรวัดเมตริกอัตราเฟรม P90 และ P99 เป็น เกณฑ์พื้นฐานที่สอดคล้องกันและตัวบ่งชี้การกระตุกตามลำดับ เมตริกเหล่านี้ จะบันทึก "ส่วนท้าย" ของประสิทธิภาพเพื่อให้คุณเพิ่มประสิทธิภาพความราบรื่น ของประสบการณ์การใช้งานของผู้เล่นได้

เมตริก

  • FPS เฉลี่ย (พื้นฐาน): เมตริกพื้นฐานนี้ให้ข้อมูลพื้นฐานทั่วไปเกี่ยวกับประสิทธิภาพของเกม แม้ว่าจะเป็นเกณฑ์มาตรฐานทั่วไป แต่การคำนวณค่าเฉลี่ยหมายความว่าระบบตรวจหาการลดลงของเฟรมเป็นระยะๆ และการกระตุกเล็กๆ ไม่ได้ จึงไม่เพียงพอที่จะแสดงถึงประสบการณ์ของผู้เล่นด้วยตัวมันเอง
  • FPS ที่ P90 (ค่าพื้นฐานที่สอดคล้องกันที่เปอร์เซ็นไทล์ที่ 10): แสดงว่าเฟรม 90% มีค่าเกินค่าพื้นฐานที่สอดคล้องกันนี้ และมีเพียงเฟรมที่ช้าที่สุด 10% เท่านั้นที่ใช้เวลานานกว่าในการแสดงผล หากอัตราเฟรมที่ P90 สูงและ ใกล้เคียงกับค่าเฉลี่ย แสดงว่าเกมทำงานได้ดีอย่างสม่ำเสมอสำหรับเซสชันส่วนใหญ่
  • FPS ที่เปอร์เซ็นไทล์ที่ 99 (ตัวบ่งชี้การกระตุกที่เปอร์เซ็นไทล์ที่ 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 ไม่เสถียร (การคอมไพล์ Shader / การสตรีมชิ้นงาน ติดขัด)

  • ค่าเฉลี่ย: 60 FPS (16.6 มิลลิวินาที)
  • P90: 45 FPS (22.2 มิลลิวินาที)
  • P99: 15 FPS (66.6 มิลลิวินาที)
  • การวิเคราะห์: นี่คือสถานการณ์ที่แย่ที่สุด แม้ว่าอัตราเฟรมโดยเฉลี่ยจะดูดี แต่ P99 ก็เผยให้เห็นปัญหาที่ร้ายแรง P99 ที่ 66.6 มิลลิวินาทีหมายความว่าเกมหยุดทำงานโดยสมบูรณ์เป็นเวลาหลายเฟรมพร้อมกัน ซึ่งบ่งชี้ถึงค่าผิดปกติที่รุนแรง ซึ่งมักเกิดจากคอขวดของ CPU, ความล่าช้าในการสตรีมเนื้อหา (เช่น RAM หรือพื้นที่เก็บข้อมูลช้า) หรือการกระตุกที่เกิดจากการคอมไพล์ Shader

การวัดผล

หากต้องการวัด FPS เฉลี่ย, FPS ที่เปอร์เซ็นไทล์ที่ 90 และ FPS ที่เปอร์เซ็นไทล์ที่ 99 อย่างมีประสิทธิภาพ คุณสามารถใช้วิธีต่อไปนี้ 2 วิธี วิธีแรกคือการวิเคราะห์การติดตามระบบโดยใช้ Android Performance Analyzer (APA) ซึ่งเป็นเครื่องมือสร้างโปรไฟล์ประสิทธิภาพ วิธีที่ 2 คือการใช้คำสั่ง adb dumpsys SurfaceFlinger --timestats ที่มีอยู่

1. วัดโดยใช้ APA

การใช้ APA ช่วยให้คุณบันทึกการติดตามระบบและวิเคราะห์ข้อมูลเฟรมได้อย่างแม่นยำ ผ่านการค้นหา SQL ทำตามขั้นตอนต่อไปนี้เพื่อวัดเมตริก

  1. บันทึกการติดตามด้วย APA: เรียกใช้เกมและใช้ APA เพื่อบันทึกการติดตามระบบในระหว่างส่วนที่คุณต้องการวิเคราะห์ (เช่น จุดหนึ่งในระหว่างเกมเพลย์ที่คุณสงสัยว่าเฟรมหลุด) เมื่ออุปกรณ์เชื่อมต่อแล้ว และบันทึกการติดตามเสร็จสมบูรณ์แล้ว ข้อมูลการติดตามจะโหลดในอินเทอร์เฟซ APA

    หน้าจอการจับภาพ Trace หรือหน้าจอ Trace ที่โหลดแล้ว
  2. คลิกแท็บ SQL ใน APA: เมื่อหน้าจอการวิเคราะห์การติดตามเปิดขึ้น ให้คลิกแท็บ SQL ในพื้นที่การนำทางด้านบนหรือด้านข้างของ UI เพื่อเปิดสภาพแวดล้อมของเครื่องมือประมวลผลการติดตาม ซึ่งคุณสามารถค้นหาข้อมูลได้โดยตรง

  3. วางคำค้นหา SQL ในแท็บ SQL ของ APA: คัดลอกคำค้นหา SQL ต่อไปนี้ แล้ววางลงในช่องป้อนข้อมูลคำค้นหา คําค้นหานี้จะระบุกระบวนการ SurfaceFlinger คํานวณช่วงเฟรมตาม การประทับเวลาการอัปเดตการแสดงผลจริง และหาค่า FPS เฉลี่ย, FPS 10% ล่างสุด (P90) และ FPS 1% ล่างสุด (P99)

    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), FPS 10% ล่างสุด (low_10_fps) และ FPS 1% ล่างสุด (low_1_fps) จะแสดงในตารางในบานหน้าต่างผลลัพธ์

    หน้าจอที่แสดงการค้นหา SQL ที่ดำเนินการและเมตริก 4 รายการที่ได้ซึ่งแสดงในตาราง

2. วัดโดยใช้ adb (dumpsys SurfaceFlinger)

หากต้องการวัด FPS เฉลี่ย, P90 และ P99 อย่างมีประสิทธิภาพ คุณสามารถใช้คำสั่ง dumpsys surfaceflinger timestats ของ Android ได้ เครื่องมือนี้จะแสดง 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. คำนวณ FPS ที่ P90 และ P99: หากต้องการดูเมตริก 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
    

    ก. ตัวอย่างเชิงแนวคิด (ตารางการกระจายสะสม) สมมติว่าเซสชันเกม บันทึกจำนวน 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%

    ข. ตรรกะการติดตั้งใช้งาน (รหัสเทียม) หากคุณกำลังทำให้การวิเคราะห์นี้เป็นแบบอัตโนมัติ โดยใช้สคริปต์ 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. หยุดการบันทึก: หลังจากรวบรวมข้อมูลที่จำเป็นทั้งหมดแล้ว คุณควร ปิดใช้ timestats โดยใช้แฟล็กปิดใช้

    adb shell dumpsys SurfaceFlinger --timestats -disable
    

เซสชันที่ช้า

เซสชันที่ช้าจะระบุปัญหาด้านประสิทธิภาพในโลกแห่งความเป็นจริงที่เกิดขึ้นในวงกว้าง เซสชันจะ "ช้า" หากเฟรมมากกว่า 25% ต่ำกว่าเกณฑ์ (เช่น 20 FPS) แม้ว่าเมตริกนี้จะมีประโยชน์ในการระบุปัญหาที่สำคัญในการสร้าง แต่เมตริกนี้เพียงอย่างเดียวไม่สามารถรับประกันประสบการณ์การใช้งานที่มีคุณภาพสูงและยั่งยืนได้ เกมอาจหลีกเลี่ยงเกณฑ์เซสชันช้าได้ แต่ยังคงประสบปัญหาการกระตุกเล็กๆ น้อยๆ ซึ่งทำให้ประสบการณ์การเล่นเกมที่ 60 FPS ไม่ราบรื่น

แม้ว่าทั้ง 2 เมตริกจะมาจากเวลาเฟรม แต่ "เซสชันที่ช้า" และ "อัตราเฟรม" มีบทบาทที่แตกต่างกัน เมตริก FPS เฉลี่ย, P90 และ P99 จะวัดคุณภาพและความยั่งยืนของประสิทธิภาพ โดยตรวจหาการลดลงในทันทีและจังหวะที่ไม่สอดคล้องกันซึ่งเมตริกเซสชันที่ช้าอาจมองข้ามไป

บทสรุป

การเพิ่มประสิทธิภาพที่ประสบความสำเร็จต้องใช้กลยุทธ์ที่ครอบคลุม นักพัฒนาแอปควรใช้เซสชันที่ช้าเป็นเรดาร์หลักเพื่อตรวจจับประสิทธิภาพที่ลดลงอย่างรุนแรง จากนั้นตรวจสอบ FPS เฉลี่ย, P90 และ P99 เพื่อวินิจฉัย สาเหตุที่แท้จริงและยืนยันความลื่นไหลที่แท้จริงของการเล่นเกม การผสานรวมเมตริกเหล่านี้จะช่วยให้มั่นใจได้ว่าแอปพลิเคชันของคุณจะมอบประสบการณ์ของผู้ใช้ที่ยอดเยี่ยมและยั่งยืนอย่างสม่ำเสมอ

แหล่งข้อมูลเพิ่มเติม

ดูข้อมูลเพิ่มเติมเกี่ยวกับเทคนิคการสร้างโปรไฟล์ขั้นสูง การใช้ Frame Pacing API และกลยุทธ์การเพิ่มประสิทธิภาพเฉพาะเอนจินได้ที่เอกสารประกอบสำหรับนักพัฒนาซอฟต์แวร์ Android อย่างเป็นทางการ

  • Android Vitals: เซสชันที่ช้า: ทำความเข้าใจวิธีที่ Google Play วัดและรายงานระยะเวลาที่การแสดงผลช้าอย่างต่อเนื่อง ซึ่งส่งผลโดยตรง ต่อประสบการณ์ของผู้ใช้ "เซสชันที่ช้า" หมายถึงเซสชันของผู้ใช้ ที่มีเฟรมช้ามากกว่า 25% (เช่น ใช้เวลามากกว่า 50 มิลลิวินาที ซึ่งเทียบเท่ากับ 20 FPS)
  • นักพัฒนาแอป Android: เพิ่มประสิทธิภาพเกม: สำรวจฮับส่วนกลาง สำหรับการเพิ่มประสิทธิภาพเกม Android คู่มือฉบับสมบูรณ์นี้ครอบคลุมแนวทางปฏิบัติแนะนำ เครื่องมือสร้างโปรไฟล์ (เช่น APA และ Perfetto) เพื่อช่วยให้คุณเพิ่มประสิทธิภาพโดยรวมของเกมได้สูงสุด