1#!/usr/bin/env python3 2# Copyright (C) 2023 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License a 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16from python.generators.diff_tests.testing import Path, DataPath, Metric 17from python.generators.diff_tests.testing import Csv, Json, TextProto 18from python.generators.diff_tests.testing import DiffTestBlueprint 19from python.generators.diff_tests.testing import TestSuite 20 21 22class GraphicsMetrics(TestSuite): 23 # Android SurfaceFlinger metrics 24 def test_frame_missed_event_frame_missed(self): 25 return DiffTestBlueprint( 26 trace=Path('frame_missed.py'), 27 query=""" 28 SELECT RUN_METRIC('android/android_surfaceflinger.sql'); 29 30 SELECT ts, dur 31 FROM android_surfaceflinger_event; 32 """, 33 out=Csv(""" 34 "ts","dur" 35 100,1 36 102,1 37 103,1 38 """)) 39 40 def test_frame_missed_metrics(self): 41 return DiffTestBlueprint( 42 trace=Path('frame_missed.py'), 43 query=Metric('android_surfaceflinger'), 44 out=TextProto(r""" 45 android_surfaceflinger { 46 missed_frames: 3 47 missed_hwc_frames: 0 48 missed_gpu_frames: 0 49 missed_frame_rate: 0.42857142857142855 # = 3/7 50 gpu_invocations: 0 51 metrics_per_display: { 52 display_id: "101" 53 missed_frames: 2 54 missed_hwc_frames: 0 55 missed_gpu_frames: 0 56 missed_frame_rate: 0.5 57 } 58 metrics_per_display: { 59 display_id: "102" 60 missed_frames: 1 61 missed_hwc_frames: 0 62 missed_gpu_frames: 0 63 missed_frame_rate: 0.33333333333333333 64 } 65 } 66 """)) 67 68 def test_surfaceflinger_gpu_invocation(self): 69 return DiffTestBlueprint( 70 trace=Path('surfaceflinger_gpu_invocation.py'), 71 query=Metric('android_surfaceflinger'), 72 out=TextProto(r""" 73 android_surfaceflinger { 74 missed_frames: 0 75 missed_hwc_frames: 0 76 missed_gpu_frames: 0 77 gpu_invocations: 4 78 avg_gpu_waiting_dur_ms: 4 79 total_non_empty_gpu_waiting_dur_ms: 11 80 } 81 """)) 82 83 # GPU metrics 84 def test_gpu_metric(self): 85 return DiffTestBlueprint( 86 trace=Path('gpu_metric.py'), 87 query=Metric('android_gpu'), 88 out=TextProto(r""" 89 android_gpu { 90 processes { 91 name: "app_1" 92 mem_max: 8 93 mem_min: 2 94 mem_avg: 3 95 } 96 processes { 97 name: "app_2" 98 mem_max: 10 99 mem_min: 6 100 mem_avg: 8 101 } 102 mem_max: 4 103 mem_min: 1 104 mem_avg: 1 105 } 106 """)) 107 108 def test_gpu_frequency_metric(self): 109 return DiffTestBlueprint( 110 trace=Path('gpu_frequency_metric.textproto'), 111 query=Metric('android_gpu'), 112 out=Path('gpu_frequency_metric.out')) 113 114 # Android Jank CUJ metric 115 def test_android_jank_cuj(self): 116 return DiffTestBlueprint( 117 trace=Path('android_jank_cuj.py'), 118 query=Metric('android_jank_cuj'), 119 out=Path('android_jank_cuj.out')) 120 121 def test_android_jank_cuj_query(self): 122 return DiffTestBlueprint( 123 trace=Path('android_jank_cuj.py'), 124 query=Path('android_jank_cuj_query_test.sql'), 125 out=Path('android_jank_cuj_query.out')) 126 127 # Composition layer 128 def test_composition_layer_count(self): 129 return DiffTestBlueprint( 130 trace=Path('composition_layer.py'), 131 query=""" 132 SELECT RUN_METRIC('android/android_hwcomposer.sql'); 133 134 SELECT display_id, AVG(value) 135 FROM total_layers 136 GROUP BY display_id; 137 """, 138 out=Csv(""" 139 "display_id","AVG(value)" 140 "0",3.000000 141 "1",5.000000 142 """)) 143 144 # G2D metrics TODO(rsavitski): find a real trace and double-check that the 145 # is realistic. One kernel's source I checked had tgid=0 for all counter 146 # Initial support was added/discussed in b/171296908. 147 def test_g2d_metrics(self): 148 return DiffTestBlueprint( 149 trace=Path('g2d_metrics.textproto'), 150 query=Metric('g2d'), 151 out=Path('g2d_metrics.out')) 152 153 # Composer execution 154 def test_composer_execution(self): 155 return DiffTestBlueprint( 156 trace=Path('composer_execution.py'), 157 query=""" 158 SELECT RUN_METRIC('android/composer_execution.sql', 159 'output', 'hwc_execution_spans'); 160 161 SELECT 162 validation_type, 163 display_id, 164 COUNT(*) AS count, 165 SUM(execution_time_ns) AS total 166 FROM hwc_execution_spans 167 GROUP BY validation_type, display_id 168 ORDER BY validation_type, display_id; 169 """, 170 out=Csv(""" 171 "validation_type","display_id","count","total" 172 "separated_validation","1",1,200 173 "skipped_validation","0",2,200 174 "skipped_validation","1",1,100 175 "unknown","1",1,0 176 "unskipped_validation","0",1,200 177 """)) 178 179 # Display metrics 180 def test_display_metrics(self): 181 return DiffTestBlueprint( 182 trace=Path('display_metrics.py'), 183 query=Metric('display_metrics'), 184 out=TextProto(r""" 185 display_metrics { 186 total_duplicate_frames: 0 187 duplicate_frames_logged: 0 188 total_dpu_underrun_count: 0 189 refresh_rate_switches: 5 190 refresh_rate_stats { 191 refresh_rate_fps: 60 192 count: 2 193 total_dur_ms: 2 194 avg_dur_ms: 1 195 } 196 refresh_rate_stats { 197 refresh_rate_fps: 90 198 count: 2 199 total_dur_ms: 2 200 avg_dur_ms: 1 201 } 202 refresh_rate_stats { 203 refresh_rate_fps: 120 204 count: 1 205 total_dur_ms: 2 206 avg_dur_ms: 2 207 } 208 update_power_state { 209 avg_runtime_micro_secs: 4000 210 } 211 } 212 """)) 213 214 # DPU vote clock and bandwidth 215 def test_dpu_vote_clock_bw(self): 216 return DiffTestBlueprint( 217 trace=Path('dpu_vote_clock_bw.textproto'), 218 query=Metric('android_hwcomposer'), 219 out=TextProto(r""" 220 android_hwcomposer { 221 skipped_validation_count: 0 222 unskipped_validation_count: 0 223 separated_validation_count: 0 224 unknown_validation_count: 0 225 dpu_vote_metrics { 226 tid: 237 227 avg_dpu_vote_clock: 206250 228 avg_dpu_vote_avg_bw: 210000 229 avg_dpu_vote_peak_bw: 205000 230 avg_dpu_vote_rt_bw: 271000 231 } 232 dpu_vote_metrics { 233 tid: 299 234 avg_dpu_vote_clock: 250000 235 } 236 } 237 """))