blob: ace04ede6f01831c411e0d757adf8776906e1386 [file] [log] [blame]
--
-- Copyright 2020 The Android Open Source Project
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- https://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- 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.
--
SELECT RUN_METRIC('android/cpu_info.sql');
SELECT RUN_METRIC('android/process_metadata.sql');
DROP TABLE IF EXISTS android_thread_time_in_state_base;
CREATE TABLE android_thread_time_in_state_base AS
SELECT
base.*,
IFNULL(core_type_per_cpu.core_type, 'unknown') core_type
FROM (
SELECT
ts,
utid,
EXTRACT_ARG(counter.arg_set_id, 'time_in_state_cpu_id') AS
time_in_state_cpu,
EXTRACT_ARG(counter.arg_set_id, 'freq') AS freq,
CAST(value AS INT) AS runtime_ms_counter
FROM counter
JOIN thread_counter_track ON (counter.track_id = thread_counter_track.id)
WHERE thread_counter_track.name = 'time_in_state'
) base
LEFT JOIN core_type_per_cpu ON (cpu = time_in_state_cpu);
DROP VIEW IF EXISTS android_thread_time_in_state_raw;
CREATE VIEW android_thread_time_in_state_raw AS
SELECT
utid,
time_in_state_cpu,
core_type,
freq,
MAX(runtime_ms_counter) - MIN(runtime_ms_counter) runtime_ms_diff
FROM android_thread_time_in_state_base
GROUP BY utid, time_in_state_cpu, core_type, freq;
DROP TABLE IF EXISTS android_thread_time_in_state_counters;
CREATE TABLE android_thread_time_in_state_counters AS
SELECT
utid,
raw.time_in_state_cpu,
raw.core_type,
SUM(runtime_ms_diff) AS runtime_ms,
SUM(raw.freq * runtime_ms_diff / 1000000) AS mcycles,
SUM(power * runtime_ms_diff / 3600000) AS power_profile_mah
FROM android_thread_time_in_state_raw AS raw
LEFT OUTER JOIN cpu_cluster_power AS power USING(core_type, freq)
GROUP BY utid, raw.time_in_state_cpu, raw.core_type
HAVING runtime_ms > 0;
DROP VIEW IF EXISTS android_thread_time_in_state_thread_metrics;
CREATE VIEW android_thread_time_in_state_thread_metrics AS
SELECT
utid,
RepeatedField(AndroidThreadTimeInStateMetric_MetricsByCoreType(
'time_in_state_cpu', time_in_state_cpu,
'core_type', core_type,
'runtime_ms', runtime_ms,
'mcycles', CAST(mcycles AS INT),
'power_profile_mah', power_profile_mah
)) metrics
FROM android_thread_time_in_state_counters
GROUP BY utid;
DROP VIEW IF EXISTS android_thread_time_in_state_threads;
CREATE VIEW android_thread_time_in_state_threads AS
SELECT
upid,
RepeatedField(AndroidThreadTimeInStateMetric_Thread(
'name',
thread.name,
'main_thread',
thread.is_main_thread,
'metrics_by_core_type',
android_thread_time_in_state_thread_metrics.metrics
)) threads
FROM thread
JOIN android_thread_time_in_state_thread_metrics USING (utid)
GROUP BY upid;
DROP VIEW IF EXISTS android_thread_time_in_state_process_metrics;
CREATE VIEW android_thread_time_in_state_process_metrics AS
WITH process_counters AS (
SELECT
upid,
time_in_state_cpu,
core_type,
SUM(runtime_ms) AS runtime_ms,
SUM(mcycles) AS mcycles,
SUM(power_profile_mah) AS power_profile_mah
FROM android_thread_time_in_state_counters
JOIN thread USING (utid)
GROUP BY upid, time_in_state_cpu, core_type
)
SELECT
upid,
RepeatedField(AndroidThreadTimeInStateMetric_MetricsByCoreType(
'time_in_state_cpu', time_in_state_cpu,
'core_type', core_type,
'runtime_ms', runtime_ms,
'mcycles', CAST(mcycles AS INT),
'power_profile_mah', power_profile_mah
)) metrics
FROM process_counters
GROUP BY upid;
DROP VIEW IF EXISTS android_thread_time_in_state_output;
CREATE VIEW android_thread_time_in_state_output AS
SELECT AndroidThreadTimeInStateMetric(
'processes', (
SELECT
RepeatedField(AndroidThreadTimeInStateMetric_Process(
'metadata', metadata,
'metrics_by_core_type',
android_thread_time_in_state_process_metrics.metrics,
'threads', android_thread_time_in_state_threads.threads
))
FROM process
JOIN process_metadata USING (upid)
JOIN android_thread_time_in_state_process_metrics USING (upid)
JOIN android_thread_time_in_state_threads USING (upid)
)
);
-- Ensure we always get the previous clock tick for duration in
-- android_thread_time_in_state_event_raw.
DROP VIEW IF EXISTS android_thread_time_in_state_event_clock;
CREATE VIEW android_thread_time_in_state_event_clock AS
SELECT
ts,
LAG(ts) OVER (ORDER BY ts) AS lag_ts
FROM (
SELECT DISTINCT ts from android_thread_time_in_state_base
);
DROP VIEW IF EXISTS android_thread_time_in_state_event_raw;
CREATE VIEW android_thread_time_in_state_event_raw AS
SELECT
ts,
ts - lag_ts AS dur,
upid,
core_type,
utid,
-- We need globally unique track names so add the utid even when we
-- know the name. But when we don't, also use the tid because that's what
-- the rest of the UI does.
IFNULL(thread.name, 'Thread ' || thread.tid) || ' (' || thread.utid || ')'
AS thread_track_name,
freq,
runtime_ms_counter - LAG(runtime_ms_counter)
OVER (PARTITION BY core_type, utid, freq ORDER BY ts) AS runtime_ms
FROM android_thread_time_in_state_base
-- Join to keep only utids which have non-zero runtime in the trace.
JOIN android_thread_time_in_state_counters USING (utid, core_type)
JOIN android_thread_time_in_state_event_clock USING(ts)
JOIN thread using (utid);
DROP VIEW IF EXISTS android_thread_time_in_state_event_thread;
CREATE VIEW android_thread_time_in_state_event_thread AS
SELECT
'counter' AS track_type,
thread_track_name || ' (' || core_type || ' core)' as track_name,
ts,
dur,
upid,
sum(runtime_ms * freq) as ms_freq
FROM android_thread_time_in_state_event_raw
WHERE runtime_ms IS NOT NULL
AND dur != 0
GROUP BY track_type, track_name, ts, dur, upid;
DROP VIEW IF EXISTS android_thread_time_in_state_event_global;
CREATE VIEW android_thread_time_in_state_event_global AS
SELECT
'counter' AS track_type,
'Total ' || core_type || ' core cycles / sec' as track_name,
ts,
dur,
0 AS upid,
SUM(runtime_ms * freq) AS ms_freq
FROM android_thread_time_in_state_event_raw
WHERE runtime_ms IS NOT NULL
GROUP BY ts, track_name;
DROP TABLE IF EXISTS android_thread_time_in_state_event;
CREATE TABLE android_thread_time_in_state_event AS
SELECT track_type, track_name, ts, dur, upid, ms_freq * 1000000 / dur AS value
FROM android_thread_time_in_state_event_thread
UNION ALL
SELECT track_type, track_name, ts, dur, upid, ms_freq * 1000000 / dur AS value
FROM android_thread_time_in_state_event_global
-- Biggest values at top of list in UI.
ORDER BY value DESC;