blob: 83f969b41bacbfb2b1dc465d83f1cbf5a5f22bf5 [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.
-- WebView is embedded in the hosting app's main process, which means it shares some threads
-- with the host app's work. We approximate WebView-related power usage
-- by selecting user slices that belong to WebView and estimating their power use
-- through the CPU time they consume at different core frequencies.
-- This file populates a summary table that can be used to produce metrics in different formats.
SELECT RUN_METRIC('android/android_proxy_power.sql');
SELECT RUN_METRIC('android/cpu_info.sql');
DROP TABLE IF EXISTS top_level_slice;
-- Select topmost slices from the 'toplevel' and 'Java' categories.
-- Filter out Looper events since they are likely to belong to the host app.
-- Slices are only used to calculate the contribution of the browser process,
-- renderer contribution will be calculated as the sum of all renderer processes' usage.
CREATE TABLE top_level_slice AS
SELECT *
FROM slice WHERE
depth = 0
AND ((category GLOB '*toplevel*' OR category = 'Java')
AND name NOT GLOB '*looper*');
DROP TABLE IF EXISTS webview_browser_slices;
-- Match top-level slices to threads and hosting apps.
-- This excludes any renderer slices because renderer processes are counted
-- as a whole separately.
-- Slices from Chrome browser processes are also excluded.
CREATE TABLE webview_browser_slices AS
SELECT
top_level_slice.ts,
top_level_slice.dur,
thread_track.utid,
process.upid AS upid,
extract_arg(process.arg_set_id, 'chrome.host_app_package_name') AS app_name
FROM top_level_slice
JOIN thread_track
ON top_level_slice.track_id = thread_track.id
JOIN process
ON thread.upid = process.upid
JOIN thread
ON thread_track.utid = thread.utid
WHERE process.name NOT GLOB '*SandboxedProcessService*'
AND process.name NOT GLOB '*chrome*'
AND app_name IS NOT NULL;
DROP TABLE IF EXISTS webview_browser_slices_power;
-- Assign power usage to WebView browser slices.
CREATE VIRTUAL TABLE webview_browser_slices_power
USING SPAN_JOIN(power_per_thread PARTITIONED utid,
webview_browser_slices PARTITIONED utid);
DROP TABLE IF EXISTS webview_browser_slices_power_summary;
-- Calculate the power usage of all WebView browser slices for each app
-- in milliampere-seconds.
CREATE TABLE webview_browser_slices_power_summary AS
SELECT
app_name,
SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
FROM webview_browser_slices_power
GROUP BY app_name;
DROP TABLE IF EXISTS webview_renderer_threads;
-- All threads of all WebView renderer processes.
CREATE TABLE webview_renderer_threads AS
SELECT
thread.utid AS utid,
extract_arg(process.arg_set_id, 'chrome.host_app_package_name') AS app_name
FROM process
JOIN thread
ON thread.upid = process.upid
WHERE process.name GLOB '*webview*SandboxedProcessService*'
AND app_name IS NOT NULL;
DROP TABLE IF EXISTS webview_renderer_power_summary;
-- Calculate the power usage of all WebView renderer processes for each app
-- in milliampere-seconds.
CREATE TABLE webview_renderer_power_summary AS
SELECT
app_name,
SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
FROM power_per_thread
JOIN webview_renderer_threads
ON power_per_thread.utid = webview_renderer_threads.utid
GROUP BY app_name;
DROP TABLE IF EXISTS webview_renderer_power_per_core_type;
-- Calculate the power usage of all WebView renderer processes for each app
-- in milliampere-seconds grouped by core type.
CREATE TABLE webview_renderer_power_per_core_type AS
SELECT
app_name,
core_type_per_cpu.core_type AS core_type,
SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
FROM power_per_thread
JOIN webview_renderer_threads
ON power_per_thread.utid = webview_renderer_threads.utid
JOIN core_type_per_cpu
ON power_per_thread.cpu = core_type_per_cpu.cpu
GROUP BY app_name, core_type_per_cpu.core_type;
DROP TABLE IF EXISTS host_app_threads;
-- All threads of hosting apps (this is a superset of webview_browser_slices).
-- 1) select all threads that had any WebView browser slices associated with them;
-- 2) get all threads for processes matching threads from 1).
-- For example, only some of app's threads wrote any slices, but we are selecting
-- all threads for this app's process.
-- Excludes all renderer processes and Chrome browser processes.
CREATE TABLE host_app_threads AS
SELECT
thread.utid AS utid,
thread.name AS name,
extract_arg(process.arg_set_id, 'chrome.host_app_package_name') AS app_name
FROM thread
JOIN process ON thread.upid = process.upid
WHERE thread.upid IN
(SELECT DISTINCT(webview_browser_slices.upid) FROM webview_browser_slices)
AND process.name NOT GLOB '*SandboxedProcessService*'
AND process.name NOT GLOB '*chrome*'
AND app_name IS NOT NULL;
DROP TABLE IF EXISTS host_app_power_summary;
-- Calculate the power usage of all WebView (host app+browser) processes for each app
-- in milliampere-seconds.
CREATE TABLE host_app_power_summary AS
SELECT
app_name,
SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
FROM power_per_thread
JOIN host_app_threads
ON power_per_thread.utid = host_app_threads.utid
GROUP BY app_name;
DROP TABLE IF EXISTS host_app_power_per_core_type;
-- Calculate the power usage of all WebView (host app+browser) processes for each app
-- in milliampere-seconds grouped by core type.
CREATE TABLE host_app_power_per_core_type AS
SELECT
app_name,
core_type_per_cpu.core_type AS core_type,
SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
FROM power_per_thread
JOIN host_app_threads
ON power_per_thread.utid = host_app_threads.utid
JOIN core_type_per_cpu
ON power_per_thread.cpu = core_type_per_cpu.cpu
GROUP BY app_name, core_type_per_cpu.core_type;
DROP TABLE IF EXISTS webview_only_threads;
-- A subset of the host app threads that are WebView-specific.
CREATE TABLE webview_only_threads AS
SELECT *
FROM host_app_threads
WHERE name GLOB 'Chrome*' OR name GLOB 'CookieMonster*'
OR name GLOB 'CompositorTileWorker*' OR name GLOB 'ThreadPool*ground*'
OR NAME GLOB 'ThreadPoolService*' OR name GLOB 'VizCompositorThread*'
OR name IN ('AudioThread', 'DedicatedWorker thread', 'GpuMemoryThread',
'JavaBridge', 'LevelDBEnv.IDB', 'MemoryInfra', 'NetworkService', 'VizWebView');
DROP TABLE IF EXISTS webview_only_power_summary;
-- Calculate the power usage of all WebView-specific host app threads
-- (browser + in-process renderers) for each app in milliampere-seconds.
CREATE TABLE webview_only_power_summary AS
SELECT
app_name,
SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
FROM power_per_thread
JOIN webview_only_threads
ON power_per_thread.utid = webview_only_threads.utid
GROUP BY app_name;
DROP TABLE IF EXISTS webview_only_power_per_core_type;
-- Calculate the power usage of all WebView-specific host app threads
-- for each app in milliampere-seconds grouped by core type.
CREATE TABLE webview_only_power_per_core_type AS
SELECT app_name,
core_type_per_cpu.core_type AS core_type,
SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
FROM power_per_thread
JOIN webview_only_threads
ON power_per_thread.utid = webview_only_threads.utid
JOIN core_type_per_cpu
ON power_per_thread.cpu = core_type_per_cpu.cpu
GROUP BY app_name, core_type_per_cpu.core_type;
-- Create views for output.
DROP TABLE IF EXISTS total_app_power_output;
CREATE TABLE total_app_power_output AS
SELECT
host_app_power_summary.app_name AS app_name,
host_app_power_summary.power_mas AS total_mas,
host_app_power_little_cores_mas.power_mas AS little_cores_mas,
host_app_power_big_cores_mas.power_mas AS big_cores_mas,
host_app_power_bigger_cores_mas.power_mas AS bigger_cores_mas
FROM host_app_power_summary LEFT JOIN host_app_power_per_core_type AS host_app_power_little_cores_mas
ON host_app_power_summary.app_name = host_app_power_little_cores_mas.app_name
AND host_app_power_little_cores_mas.core_type = 'little'
LEFT JOIN host_app_power_per_core_type AS host_app_power_big_cores_mas
ON host_app_power_summary.app_name = host_app_power_big_cores_mas.app_name
AND host_app_power_big_cores_mas.core_type = 'big'
LEFT JOIN host_app_power_per_core_type AS host_app_power_bigger_cores_mas
ON host_app_power_summary.app_name = host_app_power_bigger_cores_mas.app_name
AND host_app_power_bigger_cores_mas.core_type = 'bigger';
DROP TABLE IF EXISTS webview_renderer_power_output;
CREATE TABLE webview_renderer_power_output AS
SELECT
webview_renderer_power_summary.app_name AS app_name,
webview_renderer_power_summary.power_mas AS total_mas,
webview_renderer_little_power.power_mas AS little_cores_mas,
webview_renderer_big_power.power_mas AS big_cores_mas,
webview_renderer_bigger_power.power_mas AS bigger_cores_mas
FROM webview_renderer_power_summary LEFT JOIN webview_renderer_power_per_core_type AS webview_renderer_little_power
ON webview_renderer_power_summary.app_name = webview_renderer_little_power.app_name
AND webview_renderer_little_power.core_type = 'little'
LEFT JOIN webview_renderer_power_per_core_type AS webview_renderer_big_power
ON webview_renderer_power_summary.app_name = webview_renderer_big_power.app_name
AND webview_renderer_big_power.core_type = 'big'
LEFT JOIN webview_renderer_power_per_core_type AS webview_renderer_bigger_power
ON webview_renderer_power_summary.app_name = webview_renderer_bigger_power.app_name
AND webview_renderer_bigger_power.core_type = 'bigger';
DROP TABLE IF EXISTS webview_only_power_output;
CREATE TABLE webview_only_power_output AS
SELECT
webview_only_power_summary.app_name AS app_name,
webview_only_power_summary.power_mas AS total_mas,
webview_only_power_little_cores_mas.power_mas AS little_cores_mas,
webview_only_power_big_cores_mas.power_mas AS big_cores_mas,
webview_only_power_bigger_cores_mas.power_mas AS bigger_cores_mas
FROM webview_only_power_summary LEFT JOIN webview_only_power_per_core_type AS webview_only_power_little_cores_mas
ON webview_only_power_summary.app_name = webview_only_power_little_cores_mas.app_name
AND webview_only_power_little_cores_mas.core_type = 'little'
LEFT JOIN webview_only_power_per_core_type AS webview_only_power_big_cores_mas
ON webview_only_power_summary.app_name = webview_only_power_big_cores_mas.app_name
AND webview_only_power_big_cores_mas.core_type = 'big'
LEFT JOIN webview_only_power_per_core_type AS webview_only_power_bigger_cores_mas
ON webview_only_power_summary.app_name = webview_only_power_bigger_cores_mas.app_name
AND webview_only_power_bigger_cores_mas.core_type = 'bigger';
DROP TABLE IF EXISTS total_device_power;
-- Calculate the power usage of the device in milliampere-seconds.
CREATE TABLE total_device_power AS
SELECT SUM(dur * COALESCE(power_ma, 0) / 1e9) AS power_mas
FROM power_per_thread;