Commit a7f0b818 authored by Mikhail Khokhlov's avatar Mikhail Khokhlov Committed by Commit Bot

[tools/perf] Use window functions to speed up queries

Now that trace_processor_shell built from Chrome supports windows
functions, we can take advantage of them.

Bug: b/150125501
Change-Id: I7e6c93b7b570003c1fc97fda7bbb63cbb388b419
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2107483
Commit-Queue: Mikhail Khokhlov <khokhlov@google.com>
Reviewed-by: default avatarStephen Nusko <nuskos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#751292}
parent 3f6b001d
...@@ -18,10 +18,9 @@ ...@@ -18,10 +18,9 @@
-- Get the GestureScrollUpdate events by name ordered by timestamp, compute -- Get the GestureScrollUpdate events by name ordered by timestamp, compute
-- the number of frames (relative to 60 fps) that each event took. 1.6e+7 is -- the number of frames (relative to 60 fps) that each event took. 1.6e+7 is
-- 16 ms in nanoseconds. -- 16 ms in nanoseconds.
-- Note that here and further below the result is a table not a view because CREATE VIEW GestureScrollUpdates AS
-- it speeds up the metric computation.
CREATE TABLE GestureScrollUpdates AS
SELECT SELECT
ROW_NUMBER() OVER (ORDER BY ts ASC) AS rowNumber,
id AS ScrollId, id AS ScrollId,
ts AS ScrollTs, ts AS ScrollTs,
arg_set_id AS ScrollArgSetId, arg_set_id AS ScrollArgSetId,
...@@ -34,23 +33,13 @@ WHERE ...@@ -34,23 +33,13 @@ WHERE
name = 'InputLatency::GestureScrollUpdate' name = 'InputLatency::GestureScrollUpdate'
ORDER BY ScrollTs; ORDER BY ScrollTs;
-- TODO(khokhlov): This is pretty slow and should be rewritten using window
-- functions when they are enabled in Chrome's sqlite.
CREATE TABLE GestureScrollUpdatesWithRowNumbers AS
SELECT
(SELECT COUNT(*)
FROM GestureScrollUpdates prev
WHERE prev.ScrollTs < next.ScrollTs) + 1 as rowNumber,
*
FROM
GestureScrollUpdates next;
-- This takes the GestureScrollUpdate and joins it to the previous row (NULL -- This takes the GestureScrollUpdate and joins it to the previous row (NULL
-- if there isn't one) and the next row (NULL if there isn't one). And then -- if there isn't one) and the next row (NULL if there isn't one). And then
-- computes whether the duration of the event (relative to 60 fps) varied by -- computes whether the duration of the event (relative to 60 fps) varied by
-- more than 0.5 (which is 1/2 of 16 ms). -- more than 0.5 (which is 1/2 of 16 ms).
CREATE TABLE ScrollJanksComplete AS CREATE VIEW ScrollJanksComplete AS
SELECT SELECT
ROW_NUMBER() OVER (ORDER BY currTs ASC) AS rowNumber,
currScrollId, currScrollId,
currTs, currTs,
currScrollFramesExact, currScrollFramesExact,
...@@ -83,23 +72,12 @@ FROM ( ...@@ -83,23 +72,12 @@ FROM (
curr.ScrollFramesExact AS currScrollFramesExact, curr.ScrollFramesExact AS currScrollFramesExact,
prev.ScrollFramesExact AS prevScrollFramesExact prev.ScrollFramesExact AS prevScrollFramesExact
FROM FROM
GestureScrollUpdatesWithRowNumbers curr LEFT JOIN GestureScrollUpdates curr LEFT JOIN
GestureScrollUpdatesWithRowNumbers prev ON prev.rowNumber + 1 = curr.rowNumber GestureScrollUpdates prev ON prev.rowNumber + 1 = curr.rowNumber
) currprev JOIN ) currprev JOIN
GestureScrollUpdatesWithRowNumbers next ON currprev.currRowNumber + 1 = next.rowNumber GestureScrollUpdates next ON currprev.currRowNumber + 1 = next.rowNumber
ORDER BY currprev.currTs ASC; ORDER BY currprev.currTs ASC;
-- TODO(khokhlov): This is pretty slow and should be rewritten using window
-- functions when they are enabled in Chrome's sqlite.
CREATE TABLE ScrollJanksCompleteWithRowNumbers AS
SELECT
(SELECT COUNT(*)
FROM ScrollJanksComplete prev
WHERE prev.currTs < next.currTs) + 1 as rowNumber,
*
FROM
ScrollJanksComplete next;
-- This just lists outs the rowNumber (which is ordered by timestamp) and -- This just lists outs the rowNumber (which is ordered by timestamp) and
-- whether it was a janky slice (as defined by comparing to both the next and -- whether it was a janky slice (as defined by comparing to both the next and
-- previous slice). -- previous slice).
...@@ -110,7 +88,7 @@ CREATE VIEW ScrollJanks AS ...@@ -110,7 +88,7 @@ CREATE VIEW ScrollJanks AS
(nextJank AND prevJank IS NULL) OR (nextJank AND prevJank IS NULL) OR
(prevJank AND nextJank IS NULL) (prevJank AND nextJank IS NULL)
AS Jank AS Jank
FROM ScrollJanksCompleteWithRowNumbers; FROM ScrollJanksComplete;
-- This sums the number of periods with sequential janky slices. When Chrome -- This sums the number of periods with sequential janky slices. When Chrome
-- experiences a jank it often stumbles for a while, this attempts to -- experiences a jank it often stumbles for a while, this attempts to
......
...@@ -46,10 +46,11 @@ ...@@ -46,10 +46,11 @@
-- IDs to group them together into scrolls later and the timestamp and duration -- IDs to group them together into scrolls later and the timestamp and duration
-- to compute the duration of the scroll. -- to compute the duration of the scroll.
DROP TABLE IF EXISTS ScrollBeginsAndEnds; DROP VIEW IF EXISTS ScrollBeginsAndEnds;
CREATE TABLE ScrollBeginsAndEnds AS CREATE VIEW ScrollBeginsAndEnds AS
SELECT SELECT
ROW_NUMBER() OVER (ORDER BY ts ASC) AS rowNumber,
name, name,
id AS scrollId, id AS scrollId,
ts AS scrollTs, ts AS scrollTs,
...@@ -63,31 +64,17 @@ CREATE TABLE ScrollBeginsAndEnds AS ...@@ -63,31 +64,17 @@ CREATE TABLE ScrollBeginsAndEnds AS
) )
ORDER BY ts ASC; ORDER BY ts ASC;
-- TODO(nuskos): Once chromium TBMv3 supports windowing functions use
-- ROW_NUMBER(ORDER BY ts ASC) OVER() instead.
DROP TABLE IF EXISTS ScrollBeginsAndEndsRowNumbers;
CREATE TABLE ScrollBeginsAndEndsRowNumbers AS
SELECT
(SELECT COUNT(*)
FROM ScrollBeginsAndEnds prev
WHERE prev.scrollTs < next.scrollTs) + 1 as rowNumber,
*
FROM
ScrollBeginsAndEnds next;
-- Now we take the Begin and the End events and join the information into a -- Now we take the Begin and the End events and join the information into a
-- single row per scroll. -- single row per scroll.
DROP TABLE IF EXISTS JoinedScrollBeginsAndEnds; DROP VIEW IF EXISTS JoinedScrollBeginsAndEnds;
CREATE TABLE JoinedScrollBeginsAndEnds AS CREATE VIEW JoinedScrollBeginsAndEnds AS
SELECT SELECT
begin.scrollId AS beginId, begin.scrollId AS beginId,
begin.scrollTs AS scrollBegin, begin.scrollTs AS scrollBegin,
end.scrollTs + end.scrollDur AS maybeScrollEnd end.scrollTs + end.scrollDur AS maybeScrollEnd
FROM ScrollBeginsAndEndsRowNumbers begin JOIN ScrollBeginsAndEndsRowNumbers end ON FROM ScrollBeginsAndEnds begin JOIN ScrollBeginsAndEnds end ON
begin.rowNumber + 1 = end.rowNumber AND begin.rowNumber + 1 = end.rowNumber AND
begin.name = 'InputLatency::GestureScrollBegin' AND begin.name = 'InputLatency::GestureScrollBegin' AND
end.name = 'InputLatency::GestureScrollEnd'; end.name = 'InputLatency::GestureScrollEnd';
...@@ -101,10 +88,11 @@ CREATE TABLE JoinedScrollBeginsAndEnds AS ...@@ -101,10 +88,11 @@ CREATE TABLE JoinedScrollBeginsAndEnds AS
-- and can't reasonably determine what it should be. We have separate tracking -- and can't reasonably determine what it should be. We have separate tracking
-- to ensure this only happens at the end of the trace. -- to ensure this only happens at the end of the trace.
DROP TABLE IF EXISTS GestureScrollUpdates; DROP VIEW IF EXISTS GestureScrollUpdates;
CREATE TABLE GestureScrollUpdates AS CREATE VIEW GestureScrollUpdates AS
SELECT SELECT
ROW_NUMBER() OVER (ORDER BY ts ASC) AS rowNumber,
beginId, beginId,
scrollBegin, scrollBegin,
CASE WHEN CASE WHEN
...@@ -139,21 +127,6 @@ FROM JoinedScrollBeginsAndEnds beginAndEnd LEFT JOIN ( ...@@ -139,21 +127,6 @@ FROM JoinedScrollBeginsAndEnds beginAndEnd LEFT JOIN (
scrollUpdate.ts >= beginAndEnd.ScrollBegin scrollUpdate.ts >= beginAndEnd.ScrollBegin
ORDER BY ts ASC; ORDER BY ts ASC;
-- TODO(nuskos): Once chromium TBMv3 supports windowing functions use
-- ROW_NUMBER(ORDER BY ts ASC) OVER() instead.
DROP TABLE IF EXISTS GestureScrollUpdatesRowNumbers;
CREATE TABLE GestureScrollUpdatesRowNumbers AS
SELECT
(SELECT COUNT(*)
FROM GestureScrollUpdates prev
WHERE prev.scrollTs < next.scrollTs) + 1 as rowNumber,
*
FROM
GestureScrollUpdates next;
-- This takes the GestureScrollUpdate and joins it to the previous row (NULL -- This takes the GestureScrollUpdate and joins it to the previous row (NULL
-- if there isn't one) and the next row (NULL if there isn't one). And then -- if there isn't one) and the next row (NULL if there isn't one). And then
-- computes if the duration of the event (relative to 60 fps) increased by more -- computes if the duration of the event (relative to 60 fps) increased by more
...@@ -164,10 +137,11 @@ FROM ...@@ -164,10 +137,11 @@ FROM
-- (currBeginId == prev/next BeginId). This controls somewhat for variability -- (currBeginId == prev/next BeginId). This controls somewhat for variability
-- of scrolls. -- of scrolls.
DROP TABLE IF EXISTS ScrollJanksMaybeNull; DROP VIEW IF EXISTS ScrollJanksMaybeNull;
CREATE TABLE ScrollJanksMaybeNull AS CREATE VIEW ScrollJanksMaybeNull AS
SELECT SELECT
ROW_NUMBER() OVER (ORDER BY currScrollTs ASC) AS rowNumber,
currBeginId, currBeginId,
currUpdateDur, currUpdateDur,
currScrollDur, currScrollDur,
...@@ -198,35 +172,19 @@ CREATE TABLE ScrollJanksMaybeNull AS ...@@ -198,35 +172,19 @@ CREATE TABLE ScrollJanksMaybeNull AS
prev.beginId as prevBeginId, prev.beginId as prevBeginId,
prev.scrollFramesExact AS prevScrollFramesExact prev.scrollFramesExact AS prevScrollFramesExact
FROM FROM
GestureScrollUpdatesRowNumbers curr LEFT JOIN GestureScrollUpdates curr LEFT JOIN
GestureScrollUpdatesRowNumbers prev ON prev.rowNumber + 1 = curr.rowNumber GestureScrollUpdates prev ON prev.rowNumber + 1 = curr.rowNumber
) currprev JOIN ) currprev JOIN
GestureScrollUpdatesRowNumbers next ON currprev.currRowNumber + 1 = next.rowNumber GestureScrollUpdates next ON currprev.currRowNumber + 1 = next.rowNumber
ORDER BY currprev.currScrollTs ASC; ORDER BY currprev.currScrollTs ASC;
-- TODO(nuskos): Once chromium TBMv3 supports windowing functions use
-- ROW_NUMBER(ORDER BY ts ASC) OVER() instead.
DROP TABLE IF EXISTS ScrollJanksMaybeNullRowNumbers;
CREATE TABLE ScrollJanksMaybeNullRowNumbers AS
SELECT
(SELECT COUNT(*)
FROM ScrollJanksMaybeNull prev
WHERE prev.currScrollTs < next.currScrollTs) + 1 as rowNumber,
*
FROM
ScrollJanksMaybeNull next;
-- This just lists outs the rowNumber (which is ordered by timestamp), its jank -- This just lists outs the rowNumber (which is ordered by timestamp), its jank
-- status and information about the update and scroll overall. Basically -- status and information about the update and scroll overall. Basically
-- getting it into a next queriable format. -- getting it into a next queriable format.
DROP TABLE IF EXISTS ScrollJanks; DROP VIEW IF EXISTS ScrollJanks;
CREATE TABLE ScrollJanks AS CREATE VIEW ScrollJanks AS
SELECT SELECT
rowNumber, rowNumber,
currBeginId, currBeginId,
...@@ -235,7 +193,7 @@ CREATE TABLE ScrollJanks AS ...@@ -235,7 +193,7 @@ CREATE TABLE ScrollJanks AS
(nextJank IS NOT NULL AND nextJank) OR (nextJank IS NOT NULL AND nextJank) OR
(prevJank IS NOT NULL AND prevJank) (prevJank IS NOT NULL AND prevJank)
AS jank AS jank
FROM ScrollJanksMaybeNullRowNumbers; FROM ScrollJanksMaybeNull;
-- Compute the total amount of nanoseconds from Janky GestureScrollUpdates and -- Compute the total amount of nanoseconds from Janky GestureScrollUpdates and
-- the total amount of nanoseconds we spent scrolling in the trace. Also need -- the total amount of nanoseconds we spent scrolling in the trace. Also need
...@@ -250,9 +208,9 @@ CREATE TABLE ScrollJanks AS ...@@ -250,9 +208,9 @@ CREATE TABLE ScrollJanks AS
-- TODO(nuskos): We should support more types (floats and strings) in our -- TODO(nuskos): We should support more types (floats and strings) in our
-- metrics as well as support for specifying units (nanoseconds). -- metrics as well as support for specifying units (nanoseconds).
DROP TABLE IF EXISTS JankyNanosPerScrollNanosMaybeNull; DROP VIEW IF EXISTS JankyNanosPerScrollNanosMaybeNull;
CREATE TABLE JankyNanosPerScrollNanosMaybeNull AS CREATE VIEW JankyNanosPerScrollNanosMaybeNull AS
SELECT SELECT
SUM(jank) as numJankyUpdates, SUM(jank) as numJankyUpdates,
SUM(CASE WHEN jank = 1 THEN SUM(CASE WHEN jank = 1 THEN
...@@ -270,9 +228,9 @@ CREATE TABLE JankyNanosPerScrollNanosMaybeNull AS ...@@ -270,9 +228,9 @@ CREATE TABLE JankyNanosPerScrollNanosMaybeNull AS
) AS scrollNanos ) AS scrollNanos
FROM ScrollJanks; FROM ScrollJanks;
DROP TABLE IF EXISTS janky_time_per_scroll_processing_time; DROP VIEW IF EXISTS janky_time_per_scroll_processing_time;
CREATE TABLE janky_time_per_scroll_processing_time AS CREATE VIEW janky_time_per_scroll_processing_time AS
SELECT SELECT
(SELECT (SELECT
CASE WHEN CASE WHEN
...@@ -297,9 +255,9 @@ CREATE TABLE janky_time_per_scroll_processing_time AS ...@@ -297,9 +255,9 @@ CREATE TABLE janky_time_per_scroll_processing_time AS
-- Specify how to fill the metrics proto properly. -- Specify how to fill the metrics proto properly.
DROP TABLE IF EXISTS janky_time_per_scroll_processing_time_output; DROP VIEW IF EXISTS janky_time_per_scroll_processing_time_output;
CREATE TABLE janky_time_per_scroll_processing_time_output AS CREATE VIEW janky_time_per_scroll_processing_time_output AS
SELECT JankyTimePerScrollProcessingTime( SELECT JankyTimePerScrollProcessingTime(
'janky_time_per_scroll_processing_time_percentage', jankyPercentage, 'janky_time_per_scroll_processing_time_percentage', jankyPercentage,
'gesture_scroll_milliseconds', CAST(scrollMillis AS INT), 'gesture_scroll_milliseconds', CAST(scrollMillis AS INT),
......
...@@ -11,35 +11,22 @@ ...@@ -11,35 +11,22 @@
-- to leave only one of them. -- to leave only one of them.
-- TODO(khokhlov): Remove one of these metrics. -- TODO(khokhlov): Remove one of these metrics.
-- This selects GestureScrollUpdate events. Note the result is a table not a -- This selects GestureScrollUpdate events.
-- view to speed up the metric computation. CREATE VIEW input_latency_events AS
CREATE TABLE input_latency_events AS
SELECT SELECT
ts AS start, ts + dur AS finish ts AS start, ts + dur AS finish
FROM slice FROM slice
WHERE WHERE
name = "InputLatency::GestureScrollUpdate"; name = "InputLatency::GestureScrollUpdate";
-- This selects timestamps of finishes of GestureScrollUpdate events, and for
-- each finish, finds the timestamp of the next finish.
-- TODO(khokhlov): This query is pretty slow. Rewrite using window functions
-- when they are enabled in Chrome's sqlite.
CREATE TABLE next_finish AS
SELECT
finish,
(SELECT MIN(next.finish)
FROM input_latency_events next
WHERE next.finish > prev.finish) AS next_finish
FROM input_latency_events prev;
-- Every row of this query is a span from one event finish to the next. -- Every row of this query is a span from one event finish to the next.
-- Column names 'ts' and 'dur' are as expected by SPAN_JOIN function. -- Column names 'ts' and 'dur' are as expected by SPAN_JOIN function.
CREATE VIEW intervals_between_finishes AS CREATE VIEW intervals_between_finishes AS
SELECT SELECT
finish AS ts, finish AS ts,
next_finish AS next_ts, LEAD(finish) OVER (ORDER BY finish) AS next_ts,
next_finish - finish AS dur LEAD(finish) OVER (ORDER BY finish) - finish AS dur
FROM next_finish; FROM input_latency_events;
-- Every row of this query marks the start of some GestureScrollUpdate event. -- Every row of this query marks the start of some GestureScrollUpdate event.
-- Column names 'ts' and 'dur' are as expected by SPAN_JOIN function. -- Column names 'ts' and 'dur' are as expected by SPAN_JOIN function.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment