ממוצע פריימים לשנייה
קצב פריימים חלק ויציב הוא קריטי כדי לספק חוויית משחק באיכות גבוהה במכשירי Android. כשמודדים את ביצועי המשחק, כדאי למדוד את ממוצע הפריימים לשנייה כנקודת בסיס כדי לקבל הבנה בסיסית של חוויית המשחק. כדי להבטיח חוויית גיימינג מעולה, מומלץ לבצע אופטימיזציה של המשחק כך שיעמוד בקצב פריימים ממוצע של 60 FPS.
מסגרות לשנייה (FPS) בערכים P90 ו-P99 ליציבות
גם אם המשחק פועל בצורה חלקה עם ממוצע של 60 פריימים לשנייה, יכול להיות שיהיו בו מדי פעם תקיעות, גמגום קל ועיכובים בלתי צפויים בהזנת נתונים, וכתוצאה מכך חוויית משחק לא טובה.
לכן, יציבות הפריימים חשובה לא פחות ממעקב אחרי קצב הפריימים הממוצע. כאן צריך למדוד את מדדי קצב הפריימים P90 ו-P99 בתור קו הבסיס העקבי ומדד הגימגום, בהתאמה. המדדים האלה מתעדים את הביצועים של המשחק כדי שתוכלו לשפר את חוויית המשחק של השחקנים.
מדדים
- קצב פריימים ממוצע (ערך בסיס): המדד הבסיסי הזה מספק ערך בסיס כללי של ביצועי המשחק. זהו מדד סטנדרטי, אבל החישוב הממוצע לא מאפשר לזהות ירידות לסירוגין בקצב הפריימים וגמגום קל, ולכן הוא לא מספיק כדי לייצג את חוויית המשחק.
- P90 FPS (קצב פריימים עקבי בנקודת האחוזון ה-10): המדד הזה מציין ש-90% מהפריימים חרגו מהערך העקבי הזה, ורק 10% מהפריימים האיטיים ביותר לקחו יותר זמן לעיבוד. אם קצב הפריימים P90 גבוה וקרוב לממוצע, המשחק פועל בצורה טובה ועקבית ברוב המקרים במהלך הסשן.
- קצב פריימים (FPS) ב-P99 (אינדיקטור לגימגום באחוזון ה-1): האינדיקטור הזה מציין ש-99% מהפריימים חרגו מהאינדיקטור הזה לגימגום, ומבודד באופן ספציפי את 1% הפריימים האיטיים ביותר. המדד הזה חיוני לזיהוי של גמגומים קצרים, עיכובים בטעינת נכסים וקפיצות פתאומיות בעיבוד של נכסים כבדים שגורמים לשיבושים גלויים.
דוגמאות
השוואה בין ה-FPS הממוצע לבין מדדי P90 ו-P99 מאפשרת לאבחן במדויק את ההתנהגות הבסיסית של המשחק.
תרחיש 1: עקומת אופטימלית (משחק שעבר אופטימיזציה)
- ממוצע: 60 פריימים לשנייה (16.6 אלפיות השנייה)
- P90: 58 FPS (17.2 אלפיות השנייה)
- P99: 52 FPS (19.2 ms)
- ניתוח: המדדים קרובים מאוד זה לזה. המשחק מרגיש חלק ועקבי. אין גמגום קל, ואפילו את 1% הגרוע ביותר של הפריימים קשה להבחין בעין האנושית.
תרחיש 2: צוואר בקבוק בטעינה (מוגבל על ידי CPU/GPU)
- ממוצע: 45 FPS (22.2 אלפיות השנייה)
- P90: 40 FPS (25.0 ms)
- P99: 38 FPS (26.3 אלפיות השנייה)
- ניתוח: קצב הפריימים הממוצע נמוך יותר, אבל באופן עקבי. ערך P99 לא יורד באופן משמעותי בהשוואה לממוצע. המשמעות היא שהמערכת מוצפת בהגדרות גרפיות או במגבלות רזולוציה. המשחק לא ייראה מגמגם, אלא איטי. בדרך כלל, כשמורידים את הגדרות הגרפיקה, המדדים האלה גדלים באופן אחיד.
תרחיש 3: 60 פריימים לשנייה לא יציבים (קומפילציה של Shader / סטרימינג של נכסים גמגום)
- ממוצע: 60 פריימים לשנייה (16.6 אלפיות השנייה)
- P90: 45 FPS (22.2 ms)
- P99: 15 FPS (66.6 ms)
- ניתוח: זהו התרחיש הגרוע ביותר. למרות שקצב הפריימים הממוצע נראה מצוין, הערך P99 מצביע על בעיה קריטית. ערך P99 של 66.6ms מציין שהמשחק קופא לחלוטין למשך כמה פריימים בכל פעם. הערך הזה מצביע על חריגים קיצוניים – בדרך כלל בגלל צווארי בקבוק במעבד, עיכובים בהזרמת נכסים (למשל, זיכרון RAM או אחסון איטיים) או שיבושים שנגרמים בגלל קומפילציה של הצללה.
מדידה
כדי למדוד ביעילות את קצב הפריימים הממוצע, P90 ו-P99, אפשר להשתמש בשתי השיטות הבאות. השיטה הראשונה היא ניתוח של עקבות המערכת באמצעות Android Performance Analyzer (APA), כלי ליצירת פרופיל ביצועים. השיטה השנייה היא שימוש בפקודה הקיימת adb dumpsys SurfaceFlinger --timestats.
1. מדידה באמצעות APA
באמצעות ה-APA, אפשר לתעד מעקב מערכת ולנתח במדויק נתוני פריימים באמצעות שאילתות SQL. כדי למדוד את המדדים:
לכידת העקבות באמצעות APA: מריצים את המשחק ומשתמשים ב-APA כדי ללכוד עקבות של המערכת במהלך הקטע שרוצים לנתח (לדוגמה, נקודה במהלך המשחק שבה יש חשד לירידה בקצב הפריימים). אחרי שהמכשיר מחובר והקלטת העקבות מסתיימת, נתוני העקבות נטענים בממשק של APA.
מסך צילום המעקב או מסך המעקב שנטען לוחצים על הכרטיסייה SQL ב-APA: אחרי שפותחים את מסך ניתוח העקבות, לוחצים על הכרטיסייה SQL באזור הניווט העליון או הצדדי בממשק המשתמש כדי לפתוח את סביבת מעבד העקבות, שבה אפשר לשלוח שאילתות ישירות לנתונים.
מדביקים את שאילתת ה-SQL בכרטיסייה APA SQL: מעתיקים את שאילתת ה-SQL הבאה ומדביקים אותה בשדה להזנת קלט. השאילתה הזו מזהה את התהליך SurfaceFlinger, מחשבת את מרווחי הפריימים על סמך חותמות הזמן של עדכוני התצוגה בפועל, ומפיקה את קצב הפריימים הממוצע, את קצב הפריימים ב-10% התחתונים (P90) ואת קצב הפריימים ב-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;לוחצים על 'הפעלת שאילתה': לוחצים על הלחצן הפעלת שאילתה (או על סמל ההפעלה) ליד שדה להזנת קלט של השאילתה. אחרי שהשאילתה תסתיים, המספר הכולל של הפריימים שנמדדו (
total_presented_frames), קצב הפריימים הממוצע (average_fps), קצב הפריימים ב-10% התחתונים (low_10_fps) וקצב הפריימים ב-1% התחתונים (low_1_fps) יוצגו בטבלה בחלונית התוצאות.
מסך שבו מוצגת שאילתת ה-SQL שהופעלה וארבעת המדדים שהתקבלו מוצגים בטבלה
2. מדידה באמצעות adb (dumpsys SurfaceFlinger)
כדי למדוד ביעילות את קצב הפריימים הממוצע, P90 ו-P99, אפשר להשתמש בפקודה dumpsys surfaceflinger timestats של Android. הכלי הזה מספק את קצב הפריימים הממוצע והיסטוגרמה של תזמון 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 הממוצע לכל שכבה באופן אוטומטי, והוא מוצג ישירות בפלט של קובץ ה-dump (לדוגמה, averageFPS = 30.179).
... averageFPS = 30.179 ...חישוב ערכי FPS של P90 ו-P99: כדי למצוא את מדדי P90 ו-P99, צריך לנתח את totalFrames ואת ההיסטוגרמה של התזמון
presentToPresentשמופיעה בקובץ ה-dump.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א. דוגמה להמחשה (טבלת התפלגות מצטברת) נניח שבמהלך סשן המשחק תועד ערך של 1,000 עבור totalFrames. כדי למצוא את P90 ו-P99, מחשבים את ערכי הסף באלפיות השנייה שבהם ספירת הפריים המצטברת מגיעה ל-900 פריים (90%) ול-990 פריים (99%), בהתאמה, בספירה מהמשבצת הנמוכה ביותר באלפיות השנייה.
זמן פריים (אלפיות השנייה) מספר הפריים (היסטוגרמה) מספר הפריים המצטבר סטטוס / חישוב של אחוזון 16 אלפיות השנייה 850 850 85.0% 33ms 100 950 95.0%
(הגעת ליעד P90 של 900! → 1,000/33 = 30.3 FPS)50 אלפיות השנייה 35 985 98.5% 66ms 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הפסקת התיעוד: אחרי איסוף כל המידע הנדרש, צריך להשבית את timestats באמצעות הדגל disable:
adb shell dumpsys SurfaceFlinger --timestats -disable
סשנים איטיים
המדד סשנים איטיים מאפשר לזהות בעיות נרחבות בביצועים בעולם האמיתי. סשן מוגדר כ'איטי' אם יותר מ-25% מהפריימים יורדים מתחת לסף מסוים (לדוגמה, 20 FPS). המדד הזה שימושי לזיהוי בעיות קריטיות בבנייה, אבל הוא לא יכול להבטיח חוויה איכותית ובת קיימא. יכול להיות שמשחק לא יגיע לסף של סשן איטי, אבל עדיין יסבול מגמגום קל שיפגע בחוויה של 60 פריימים לשנייה.
המדדים 'סשן איטי' ו'קצב פריימים' מבוססים על זמני פריימים, אבל הם משמשים למטרות שונות. המדדים 'ממוצע FPS', 'P90' ו-'P99' מודדים את האיכות והקיימות של הביצועים, ומזהים ירידות מיידיות וקצב לא עקבי שהמדד 'סשן איטי' עשוי לפספס.
סיכום
כדי לבצע אופטימיזציה של הביצועים בצורה מוצלחת, צריך אסטרטגיה מקיפה. מפתחים צריכים להשתמש במדד 'סשנים איטיים' ככלי ראשי לזיהוי ירידה חמורה בביצועים, ואז לבדוק את המדדים 'מסגרות לשנייה בממוצע', P90 ו-P99 כדי לאבחן את הגורמים הבסיסיים ולבדוק את רמת החלקות בפועל של המשחק. שילוב המדדים האלה מאפשר לוודא שהאפליקציה מספקת חוויית משתמש עקבית, טובה ובת קיימא.
מקורות מידע נוספים
כדי לקבל מידע נוסף על טכניקות מתקדמות ליצירת פרופילים, על הטמעה של Frame Pacing API ועל אסטרטגיות אופטימיזציה ספציפיות למנוע, אפשר לעיין בתיעוד הרשמי למפתחי Android:
- תפקוד האפליקציה ל-Android: סשנים איטיים: הסבר על האופן שבו Google Play מודד ומדווח על תקופות ממושכות של רינדור איטי, שמשפיע ישירות על חוויית המשתמש. 'סשן איטי' מוגדר כסשן משתמש שבו יותר מ-25% מהפריימים איטיים (לדוגמה, עיבוד התמונה נמשך יותר מ-50 אלפיות השנייה, ששווה ל-20 FPS).
- Android Developers: Optimize Game Performance: מרכז מידע לאופטימיזציה של משחקים ל-Android. במדריך המקיף הזה תמצאו שיטות מומלצות וכלי פרופיל (כמו APA ו-Perfetto) שיעזרו לכם לשפר את הביצועים הכוללים של המשחק.