평균 FPS
Android 기기에서 고품질 게임 환경을 제공하려면 원활하고 안정적인 프레임 속도가 중요합니다. 게임 성능을 측정할 때는 환경에 대한 기본적인 이해를 제공하기 위해 평균 FPS를 기준 으로 측정해야 합니다. 훌륭한 게임 환경을 보장하려면 평균 프레임 속도 60FPS를 충족하도록 게임을 최적화해야 합니다.
안정성을 위한 P90 및 P99 FPS
평균 60FPS가 원활하더라도 게임에서 간헐적인 걸림, 미세한 끊김, 예측할 수 없는 입력 지연이 발생하여 플레이어 환경이 저하될 수 있습니다.
따라서 프레임 안정성은 평균 프레임 속도를 추적하는 것만큼 중요합니다. 여기서 P90 및 P99 프레임 속도 측정항목을 일관된 기준과 끊김 표시기로 각각 측정해야 합니다. 이러한 측정항목은 플레이어 환경의 원활함을 최적화할 수 있도록 성능의 '꼬리 끝'을 캡처합니다.
측정항목
- 평균 FPS (기준): 이 기본 측정항목은 게임 성능의 일반적인 기준을 제공합니다. 표준 벤치마크이지만 평균 계산은 간헐적인 프레임 삭제와 미세한 끊김을 감지할 수 없음을 의미하므로 플레이어 환경을 자체적으로 나타내기에는 충분하지 않습니다.
- P90 FPS (10% 백분위수의 일관된 기준): 이는 프레임의 90% 가 이 일관된 기준을 초과했으며 가장 느린 프레임의 10% 만 렌더링하는 데 시간이 더 오래 걸렸음을 나타냅니다. P90 프레임 속도가 높고 평균에 가까우면 게임이 세션의 대부분에서 일관되게 잘 실행됩니다.
- P99 FPS (1% 백분위수의 끊김 표시기): 이는 프레임의 99% 가 이 끊김 표시기를 초과했으며 가장 느린 프레임의 1% 를 구체적으로 격리했음을 나타냅니다. 이 측정항목은 눈에 띄는 걸림을 일으키는 미세한 끊김, 애셋 로드 지연, 갑작스러운 애셋이 많은 렌더링 급증을 포착하는 데 필수적입니다.
예
평균 FPS를 P90 및 P99 측정항목과 비교하면 게임의 기본 동작을 정확하게 진단할 수 있습니다.
시나리오 1: 최적 곡선 (최적화된 게임)
- 평균: 60FPS (16.6ms)
- P90: 58 FPS (17.2 ms)
- P99: 52 FPS (19.2 ms)
- 분석: 측정항목이 긴밀하게 클러스터링됩니다. 게임이 매우 원활하고 일관되게 느껴집니다. 미세한 끊김이 없으며 최악의 프레임 1% 도 사람의 눈에 거의 띄지 않습니다.
시나리오 2: 로드 병목 현상 (CPU/GPU 바운드)
- 평균: 45FPS (22.2ms)
- P90: 40 FPS (25.0 ms)
- P99: 38 FPS (26.3 ms)
- 분석: 평균 프레임 속도는 낮지만 일관되게 낮습니다. P99는 평균에 비해 급격하게 떨어지지 않습니다. 이는 시스템이 기본적으로 그래픽 설정 또는 해상도 제약조건에 압도되고 있음을 나타냅니다. 게임이 끊김 현상처럼 느껴지지 않고 오히려 느리게 느껴집니다. 그래픽 설정을 낮추면 일반적으로 이러한 측정항목이 균일하게 확장됩니다.
시나리오 3: 불안정한 60FPS (셰이더 컴파일 / 애셋 스트리밍 끊김)
- 평균: 60FPS (16.6ms)
- P90: 45 FPS (22.2 ms)
- P99: 15 FPS (66.6 ms)
- 분석: 최악의 시나리오입니다. 평균 프레임 속도는 우수해 보이지만 P99는 중요한 문제를 드러냅니다. P99가 66.6ms이면 게임이 한 번에 여러 프레임 동안 완전히 정지된다는 의미입니다. 이는 심각한 이상점을 나타냅니다. 일반적으로 CPU 병목 현상, 애셋 스트리밍 지연(예: 느린 RAM 또는 스토리지), 셰이더 컴파일로 인한 걸림으로 인해 발생합니다.
측정
평균 FPS, P90, P99를 효과적으로 측정하려면 Android
dumpsys surfaceflinger timestats 명령어를 사용하면 됩니다. 이 도구는 렌더링되는 모든 레이어의 평균 FPS와 presentToPresent 타이밍 히스토그램을 제공합니다. 프레임의 presentToPresent 시간은 현재 프레임과 이전 프레임이 그려지는 간격입니다.
다음은 게임의 이러한 측정항목을 수집하고 계산하는 단계별 안내입니다.
캡처 시작: enable 및 clear 플래그를 사용하여 다음 명령어를 실행하여 정보 캡처를 시작합니다.
adb shell dumpsys SurfaceFlinger --timestats -clear -enable정보 덤프: 게임이 충분히 플레이되면 dump 플래그를 사용하여 명령어를 다시 실행하여 정보를 출력합니다.
adb shell dumpsys SurfaceFlinger --timestats -dump레이어별 필터링: 덤프된 정보는 SurfaceFlinger에서 렌더링한 모든 레이어의 데이터를 제공합니다.
layerName(예: layerName = SurfaceView[com.example.yourgame...])을 기준으로 필터링하여 게임에 해당하는 섹션을 찾아야 합니다.layerName = SurfaceView[com.google.test/com.devrel.MainActivity]@0(BLAST)#132833평균 FPS 식별: 각 레이어의 평균 FPS는 자동으로 계산되며 덤프 출력에 직접 표시됩니다 (예: averageFPS = 30.179).
... averageFPS = 30.179 ...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=0A. 개념적 예 (누적 분포 표) 게임 세션에서 totalFrames 수가 1,000으로 기록되었다고 가정합니다. P90 및 P99를 찾으려면 누적 프레임 수가 각각 900프레임 (90%)과 990프레임 (99%)에 도달하는 밀리초 기준을 계산합니다. 가장 낮은 밀리초 버킷부터 계산합니다.
프레임 시간 (ms) 프레임 수 (히스토그램) 누적 프레임 수 백분위수 상태 / 계산 16ms 850 850 85.0% 33ms 100 950 95.0%
(P90 타겟 900 도달! → 1000/33 = 30.3 FPS)50ms 35 985 98.5% 66ms 10 995 99.5%
(P99 타겟 990 도달! → 1000/66 = 15.1 FPS)102ms 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캡처 중지: 필요한 정보를 모두 수집한 후 disable 플래그를 사용하여 timestats를 사용 중지해야 합니다.
adb shell dumpsys SurfaceFlinger --timestats -disable
느린 세션
느린 세션은 광범위한 실제 성능 문제를 식별합니다. 프레임의 25% 이상이 기준 (예: 20FPS) 아래로 떨어지면 세션이 '느림'입니다. 중요한 빌드 문제를 발견하는 데 유용하지만 이 측정항목만으로는 고품질의 지속 가능한 환경을 보장할 수 없습니다. 게임이 느린 세션 기준을 피할 수 있지만 원활한 60FPS 환경을 저해하는 미세한 끊김이 발생할 수 있습니다.
프레임 시간에서 파생되지만 '느린 세션'과 '프레임 속도'는 서로 다른 역할을 합니다. 평균, P90, P99 FPS 측정항목은 성능의 품질과 지속 가능성을 측정하여 느린 세션 측정항목이 간과할 수 있는 순간적인 삭제와 일관되지 않은 페이싱을 감지합니다.
결론
성능 최적화를 성공적으로 수행하려면 포괄적인 전략이 필요합니다. 개발자는 느린 세션을 기본 레이더로 사용하여 심각한 성능 저하를 포착한 다음 평균 FPS, P90, P99를 검사하여 근본 원인을 진단하고 게임플레이의 실제 원활함을 확인해야 합니다. 이러한 측정항목을 통합하면 애플리케이션이 지속적으로 지속 가능하고 뛰어난 사용자 환경을 제공할 수 있습니다.
추가 리소스
고급 프로파일링 기법, 프레임 페이싱 API 구현, 엔진별 최적화 전략에 관해 자세히 알아보려면 공식 Android 개발자 문서를 참고하세요.
- Android vitals: 느린 세션: Google Play에서 사용자 환경에 직접적인 영향을 미치는 느린 렌더링의 지속적인 기간을 측정하고 보고하는 방법을 알아보세요. '느린 세션'은 프레임의 25% 이상이 느린 사용자 세션으로 정의됩니다 (예: 50ms 초과, 20FPS에 해당).
- Android 개발자: 게임 성능 최적화: Android 게임 최적화를 위한 중앙 허브를 살펴보세요. 이 포괄적인 가이드에서는 게임의 전반적인 성능을 극대화하는 데 도움이 되는 권장사항, 프로파일링 도구 (예: Android Performance Analyzer(APA) 및 Perfetto)를 다룹니다.