tp: Migrate CUJ counter metrics from metrics to stdlib Move the CUJ counter aggregation logic from the metrics jank/internal/counters.sql into the PerfettoSQL stdlib, extending the existing android.cujs.cuj_frame_counters module. The metrics file becomes a thin compatibility shim that re-exports the stdlib table under the legacy public name. This is Step 6 of the CUJ metrics-to-stdlib migration. Change-Id: Ibafc0e6c1f06e5e15bf7b4b1ce778bebb52da15e
diff --git a/src/trace_processor/metrics/sql/android/jank/internal/counters.sql b/src/trace_processor/metrics/sql/android/jank/internal/counters.sql index 1636b9f..36b43d9 100644 --- a/src/trace_processor/metrics/sql/android/jank/internal/counters.sql +++ b/src/trace_processor/metrics/sql/android/jank/internal/counters.sql
@@ -12,48 +12,12 @@ -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. -INCLUDE PERFETTO MODULE android.cujs.base; + INCLUDE PERFETTO MODULE android.cujs.cuj_frame_counters; +-- NOTE: We preserve the legacy table name in this file because external +-- consumers and analytical pipelines outside the Perfetto project rely on it. + DROP TABLE IF EXISTS android_jank_cuj_counter_metrics; CREATE PERFETTO TABLE android_jank_cuj_counter_metrics AS --- Order CUJs to get the ts of the next CUJ with the same name. --- This is to avoid selecting counters logged for the next CUJ in case multiple --- CUJs happened in a short succession. -WITH cujs_ordered AS ( - SELECT - cuj_id, - cuj_name, - cuj_slice_name, - upid, - state, - ts_end, - CASE - WHEN process_name GLOB 'com.android.*' THEN ts_end - WHEN process_name = 'com.google.android.apps.nexuslauncher' THEN ts_end - -- Some processes publish counters just before logging the CUJ end - ELSE MAX(ts, ts_end - 4000000) - END AS ts_earliest_allowed_counter, - LEAD(ts_end) OVER (PARTITION BY cuj_name ORDER BY ts_end ASC) AS ts_end_next_cuj - FROM android_jank_cuj -) -SELECT - cuj_id, - cuj_name, - upid, - state, - _android_jank_cuj_counter_value(cuj_name, 'totalFrames', ts_earliest_allowed_counter, ts_end_next_cuj) AS total_frames, - _android_jank_cuj_counter_value(cuj_name, 'missedFrames', ts_earliest_allowed_counter, ts_end_next_cuj) AS missed_frames, - _android_jank_cuj_counter_value(cuj_name, 'missedAppFrames', ts_earliest_allowed_counter, ts_end_next_cuj) AS missed_app_frames, - _android_jank_cuj_counter_value(cuj_name, 'missedSfFrames', ts_earliest_allowed_counter, ts_end_next_cuj) AS missed_sf_frames, - _android_jank_cuj_counter_value(cuj_name, 'maxSuccessiveMissedFrames', ts_earliest_allowed_counter, ts_end_next_cuj) AS missed_frames_max_successive, - _android_jank_cuj_counter_value(cuj_name, 'totalAnimTime', ts_earliest_allowed_counter, ts_end_next_cuj) AS anim_duration_ms, - -- weighted jank is stored in janks per ms in the counters, since the counters are ints. - _android_jank_cuj_counter_value(cuj_name, 'weightedJank', ts_earliest_allowed_counter, ts_end_next_cuj) / 1000.0 AS weighted_missed_frames, - _android_jank_cuj_counter_value(cuj_name, 'weightedAppJank', ts_earliest_allowed_counter, ts_end_next_cuj) / 1000.0 AS weighted_missed_app_frames, - _android_jank_cuj_counter_value(cuj_name, 'weightedSfJank', ts_earliest_allowed_counter, ts_end_next_cuj) / 1000.0 AS weighted_missed_sf_frames, - -- convert ms to nanos to align with the unit for `dur` in the other tables - _android_jank_cuj_counter_value(cuj_name, 'maxFrameTimeMillis', ts_earliest_allowed_counter, ts_end_next_cuj) * 1000000 AS frame_dur_max, - _android_cuj_missed_vsyncs_for_callback(cuj_slice_name, ts_earliest_allowed_counter, ts_end_next_cuj, '*SF*') AS sf_callback_missed_frames, - _android_cuj_missed_vsyncs_for_callback(cuj_slice_name, ts_earliest_allowed_counter, ts_end_next_cuj, '*HWUI*') AS hwui_callback_missed_frames -FROM cujs_ordered cuj; +SELECT * FROM _android_jank_cuj_counter_metrics;
diff --git a/src/trace_processor/perfetto_sql/stdlib/android/cujs/cuj_frame_counters.sql b/src/trace_processor/perfetto_sql/stdlib/android/cujs/cuj_frame_counters.sql index 62a1ae3..3441232 100644 --- a/src/trace_processor/perfetto_sql/stdlib/android/cujs/cuj_frame_counters.sql +++ b/src/trace_processor/perfetto_sql/stdlib/android/cujs/cuj_frame_counters.sql
@@ -98,3 +98,145 @@ ORDER BY ts LIMIT 1; + +-- Counter metrics for each CUJ, aggregating all counter values. +-- Orders CUJs to get the ts of the next CUJ with the same name to avoid +-- selecting counters logged for the next CUJ in case multiple CUJs happened +-- in a short succession. +CREATE PERFETTO TABLE _android_jank_cuj_counter_metrics( + -- Unique CUJ id. + cuj_id LONG, + -- Name of the CUJ. + cuj_name STRING, + -- Process upid. + upid JOINID(process.id), + -- State of the CUJ. + state STRING, + -- Total number of frames. + total_frames LONG, + -- Number of missed frames. + missed_frames LONG, + -- Number of missed app frames. + missed_app_frames LONG, + -- Number of missed SF frames. + missed_sf_frames LONG, + -- Max successive missed frames. + missed_frames_max_successive LONG, + -- Total animation duration in ms. + anim_duration_ms LONG, + -- Weighted count of missed frames. + weighted_missed_frames DOUBLE, + -- Weighted count of missed app frames. + weighted_missed_app_frames DOUBLE, + -- Weighted count of missed SF frames. + weighted_missed_sf_frames DOUBLE, + -- Max frame duration in nanoseconds. + frame_dur_max LONG, + -- Number of missed SF callback frames. + sf_callback_missed_frames LONG, + -- Number of missed HWUI callback frames. + hwui_callback_missed_frames LONG +) +AS +WITH + cujs_ordered AS ( + SELECT + cuj_id, + cuj_name, + cuj_slice_name, + upid, + state, + ts_end, + CASE + WHEN process_name GLOB 'com.android.*' THEN ts_end + WHEN process_name = 'com.google.android.apps.nexuslauncher' THEN ts_end + -- Some processes publish counters just before logging the CUJ end + ELSE MAX(ts, ts_end - 4000000) + END AS ts_earliest_allowed_counter, + LEAD(ts_end) OVER (PARTITION BY cuj_name ORDER BY ts_end) AS ts_end_next_cuj + FROM android_jank_cuj + ) +SELECT + cuj_id, + cuj_name, + upid, + state, + _android_jank_cuj_counter_value( + cuj_name, + 'totalFrames', + ts_earliest_allowed_counter, + ts_end_next_cuj + ) AS total_frames, + _android_jank_cuj_counter_value( + cuj_name, + 'missedFrames', + ts_earliest_allowed_counter, + ts_end_next_cuj + ) AS missed_frames, + _android_jank_cuj_counter_value( + cuj_name, + 'missedAppFrames', + ts_earliest_allowed_counter, + ts_end_next_cuj + ) AS missed_app_frames, + _android_jank_cuj_counter_value( + cuj_name, + 'missedSfFrames', + ts_earliest_allowed_counter, + ts_end_next_cuj + ) AS missed_sf_frames, + _android_jank_cuj_counter_value( + cuj_name, + 'maxSuccessiveMissedFrames', + ts_earliest_allowed_counter, + ts_end_next_cuj + ) AS missed_frames_max_successive, + _android_jank_cuj_counter_value( + cuj_name, + 'totalAnimTime', + ts_earliest_allowed_counter, + ts_end_next_cuj + ) AS anim_duration_ms, + -- weighted jank is stored in janks per ms in the counters, since the counters are ints. + _android_jank_cuj_counter_value( + cuj_name, + 'weightedJank', + ts_earliest_allowed_counter, + ts_end_next_cuj + ) + / 1000.0 AS weighted_missed_frames, + _android_jank_cuj_counter_value( + cuj_name, + 'weightedAppJank', + ts_earliest_allowed_counter, + ts_end_next_cuj + ) + / 1000.0 AS weighted_missed_app_frames, + _android_jank_cuj_counter_value( + cuj_name, + 'weightedSfJank', + ts_earliest_allowed_counter, + ts_end_next_cuj + ) + / 1000.0 AS weighted_missed_sf_frames, + -- convert ms to nanos to align with the unit for `dur` in the other tables + _android_jank_cuj_counter_value( + cuj_name, + 'maxFrameTimeMillis', + ts_earliest_allowed_counter, + ts_end_next_cuj + ) + * 1000000 AS frame_dur_max, + _android_cuj_missed_vsyncs_for_callback( + cuj_slice_name, + ts_earliest_allowed_counter, + ts_end_next_cuj, + '*SF*' + ) AS sf_callback_missed_frames, + _android_cuj_missed_vsyncs_for_callback( + cuj_slice_name, + ts_earliest_allowed_counter, + ts_end_next_cuj, + '*HWUI*' + ) AS hwui_callback_missed_frames +FROM cujs_ordered AS cuj;