Merge "Perfetto metrics for Multiuser"
diff --git a/CHANGELOG b/CHANGELOG
index e8e0dd2..128093a 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -3,6 +3,8 @@
* Removed DCHECK that would cause crashes when a debug build of the service
is used with a producer built with -DNDEBUG.
Trace Processor:
+ * Added reqiurement of separating queries by semi-colon (;) followed by
+ new-line when specifying a query file with -q to trace processor shell.
* Added "ancestor_slice_by_stack" and "descendant_slice_by_stack" table
functions to walk up and down the slice stacks.
UI:
diff --git a/src/trace_processor/metrics/android/android_sysui_cuj.sql b/src/trace_processor/metrics/android/android_sysui_cuj.sql
index 4d5bcd8..6b5c58d 100644
--- a/src/trace_processor/metrics/android/android_sysui_cuj.sql
+++ b/src/trace_processor/metrics/android/android_sysui_cuj.sql
@@ -34,7 +34,7 @@
AND slice.dur > 0
AND (
process.name LIKE 'com.google.android%'
- OR process.name = 'com.android.systemui')
+ OR process.name LIKE 'com.android.%')
ORDER BY ts desc
LIMIT 1;
diff --git a/src/trace_processor/trace_processor_shell.cc b/src/trace_processor/trace_processor_shell.cc
index 48d1d71..8caa693 100644
--- a/src/trace_processor/trace_processor_shell.cc
+++ b/src/trace_processor/trace_processor_shell.cc
@@ -542,10 +542,6 @@
return it->Status();
}
-bool IsBlankLine(const std::string& buffer) {
- return buffer == "\n" || buffer == "\r\n";
-}
-
bool IsCommentLine(const std::string& buffer) {
return base::StartsWith(buffer, "--");
}
@@ -561,8 +557,6 @@
std::string sql_query;
while (fgets(buffer, sizeof(buffer), input)) {
std::string line = base::TrimLeading(buffer);
- if (IsBlankLine(line))
- break;
if (IsCommentLine(line))
continue;
diff --git a/test/trace_processor/parsing/android_log_msgs.sql b/test/trace_processor/parsing/android_log_msgs.sql
index dfbd6a3..02093ca 100644
--- a/test/trace_processor/parsing/android_log_msgs.sql
+++ b/test/trace_processor/parsing/android_log_msgs.sql
@@ -13,7 +13,7 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-create view v1 as select tag, count(*) from android_logs group by tag order by 2 desc limit 5
+create view v1 as select tag, count(*) from android_logs group by tag order by 2 desc limit 5;
create view v2 as select tag, count(*) from android_logs group by tag order by 2 asc limit 5;
@@ -27,4 +27,4 @@
select '-----', 0 union all
select * from v3 union all
select '-----', 0 union all
-select * from v4;
\ No newline at end of file
+select * from v4;
diff --git a/test/trace_processor/parsing/b120487929.sql b/test/trace_processor/parsing/b120487929.sql
index 179d324..a266d7a 100644
--- a/test/trace_processor/parsing/b120487929.sql
+++ b/test/trace_processor/parsing/b120487929.sql
@@ -38,19 +38,19 @@
where name = 'cpuidle';
create virtual table freq_idle
- using span_join(freq_view PARTITIONED cpu, idle_view PARTITIONED cpu)
+ using span_join(freq_view PARTITIONED cpu, idle_view PARTITIONED cpu);
create virtual table window_freq_idle using window;
create virtual table span_freq_idle
- using span_join(freq_idle PARTITIONED cpu, window_freq_idle)
+ using span_join(freq_idle PARTITIONED cpu, window_freq_idle);
update window_freq_idle
set
window_start=(select min(ts) from sched),
window_dur=(select max(ts) - min(ts) from sched),
quantum=1000000
- where rowid = 0
+ where rowid = 0;
create view counter_view
as select
@@ -66,6 +66,6 @@
when 4294967295 then freq_value
else idle_value
end as value
- from span_freq_idle
+ from span_freq_idle;
-select cpu, name, value, sum(dur) from counter_view group by cpu, name, value
+select cpu, name, value, sum(dur) from counter_view group by cpu, name, value;
diff --git a/test/trace_processor/tables/nulls.sql b/test/trace_processor/tables/nulls.sql
index 44e5132..cccbc47 100644
--- a/test/trace_processor/tables/nulls.sql
+++ b/test/trace_processor/tables/nulls.sql
@@ -37,6 +37,6 @@
(2, NULL, NULL, NULL, "test", NULL),
(1, "other", NULL, NULL, NULL, NULL),
(4, NULL, NULL, NULL, NULL, 1.0),
-(NULL, "test", 1.0, 1, NULL, NULL)
+(NULL, "test", 1.0, 1, NULL, NULL);
SELECT * from null_test;
diff --git a/ui/release/channels.json b/ui/release/channels.json
index f267c6a..c13f7da 100644
--- a/ui/release/channels.json
+++ b/ui/release/channels.json
@@ -2,11 +2,11 @@
"channels": [
{
"name": "stable",
- "rev": "0f82b928d7a9f24bafabe50daa1f50b11fd3848d"
+ "rev": "448de39fa777ebfb143fb407b3f78ba6f422ae04"
},
{
"name": "canary",
- "rev": "3cedc5a20af20fceef7439e7f94fc33fe2da0d05"
+ "rev": "e8ca899d9d2bfba9b68f8e05908372c1379c410b"
},
{
"name": "autopush",
diff --git a/ui/src/assets/record.scss b/ui/src/assets/record.scss
index 73198ba..e360857 100644
--- a/ui/src/assets/record.scss
+++ b/ui/src/assets/record.scss
@@ -787,18 +787,6 @@
outline: none;
-webkit-appearance: none;
- &:not(.multicolumn) {
- overflow: hidden;
- height: 25px;
- padding: 0 5px;
- &:focus, &:hover {
- height: 30vh;
- position: absolute;
- overflow: auto;
- box-shadow: 0 0 15px 0 #eee;
- }
- }
-
option, optgroup {
@include transition();
min-height: 25px;
@@ -820,6 +808,23 @@
}
}
+ &.singlecolumn {
+ margin: var(--record-section-padding) 0;
+ padding: 0;
+ max-width: 50%;
+ width: 50%;
+ overflow-y: auto;
+ height: 400px;
+ optgroup {
+ display: grid;
+ padding: 0;
+ grid-template-columns: 1fr;
+ }
+ option {
+ margin: 0;
+ }
+ }
+
&.multicolumn {
padding: 0;
max-width: 100%;
diff --git a/ui/src/common/engine.ts b/ui/src/common/engine.ts
index 8602089..065df54 100644
--- a/ui/src/common/engine.ts
+++ b/ui/src/common/engine.ts
@@ -25,8 +25,9 @@
import {NUM, NUM_NULL, STR} from './query_result';
import {
createQueryResult,
+ QueryError,
QueryResult,
- WritableQueryResult
+ WritableQueryResult,
} from './query_result';
import {TimeSpan} from './time';
@@ -44,7 +45,6 @@
endLoading(): void {}
}
-export class QueryError extends Error {}
// This is used to skip the decoding of queryResult from protobufjs and deal
// with it ourselves. See the comment below around `QueryResult.decode = ...`.
diff --git a/ui/src/common/query_result.ts b/ui/src/common/query_result.ts
index e882624..70186cf 100644
--- a/ui/src/common/query_result.ts
+++ b/ui/src/common/query_result.ts
@@ -60,6 +60,8 @@
export type ColumnType = string|number|null;
+export class QueryError extends Error {}
+
// One row extracted from an SQL result:
export interface Row {
[key: string]: ColumnType;
@@ -335,7 +337,7 @@
if (this._error === undefined) {
promise.resolve(arg);
} else {
- promise.reject(new Error(this._error));
+ promise.reject(new QueryError(this._error));
}
}
}
diff --git a/ui/src/common/state.ts b/ui/src/common/state.ts
index b4a0f83..fec17e5 100644
--- a/ui/src/common/state.ts
+++ b/ui/src/common/state.ts
@@ -59,9 +59,10 @@
export const MAX_TIME = 180;
// 3: TrackKindPriority and related sorting changes.
-// 5: Move a large number of items off frontendLocalState and onto state
+// 5: Move a large number of items off frontendLocalState and onto state.
// 6: Common PivotTableConfig and pivot table specific PivotTableState.
-export const STATE_VERSION = 6;
+// 7: Split Chrome categories in two and add 'symbolize ksyms' flag.
+export const STATE_VERSION = 7;
export const SCROLLING_TRACK_GROUP = 'ScrollingTracks';
@@ -418,8 +419,7 @@
export function isAdbTarget(target: RecordingTarget):
target is AdbRecordingTarget {
- if ((target as AdbRecordingTarget).serial) return true;
- return false;
+ return !!(target as AdbRecordingTarget).serial;
}
export function hasActiveProbes(config: RecordConfig) {
@@ -496,6 +496,7 @@
procStatsPeriodMs: number;
chromeCategoriesSelected: string[];
+ chromeHighOverheadCategoriesSelected: string[];
chromeLogs: boolean;
taskScheduling: boolean;
@@ -573,6 +574,7 @@
procStatsPeriodMs: 1000,
chromeCategoriesSelected: [],
+ chromeHighOverheadCategoriesSelected: [],
chromeLogs: false,
taskScheduling: false,
diff --git a/ui/src/controller/metrics_controller.ts b/ui/src/controller/metrics_controller.ts
index 21ca500..92afb8a 100644
--- a/ui/src/controller/metrics_controller.ts
+++ b/ui/src/controller/metrics_controller.ts
@@ -13,8 +13,8 @@
// limitations under the License.
import {Actions} from '../common/actions';
-import {Engine, QueryError} from '../common/engine';
-import {STR} from '../common/query_result';
+import {Engine} from '../common/engine';
+import {QueryError, STR} from '../common/query_result';
import {publishMetricResult} from '../frontend/publish';
import {Controller} from './controller';
diff --git a/ui/src/controller/record_controller.ts b/ui/src/controller/record_controller.ts
index db03bb5..1b2c363 100644
--- a/ui/src/controller/record_controller.ts
+++ b/ui/src/controller/record_controller.ts
@@ -115,6 +115,8 @@
const atraceApps = new Set<string>();
const chromeCategories = new Set<string>();
uiCfg.chromeCategoriesSelected.forEach(it => chromeCategories.add(it));
+ uiCfg.chromeHighOverheadCategoriesSelected.forEach(
+ it => chromeCategories.add(it));
let procThreadAssociationPolling = false;
let procThreadAssociationFtrace = false;
diff --git a/ui/src/controller/record_controller_jsdomtest.ts b/ui/src/controller/record_controller_jsdomtest.ts
index 516c04c..916054b 100644
--- a/ui/src/controller/record_controller_jsdomtest.ts
+++ b/ui/src/controller/record_controller_jsdomtest.ts
@@ -157,7 +157,8 @@
test('ChromeMemoryConfig', () => {
const config = createEmptyRecordConfig();
- config.chromeCategoriesSelected = ['disabled-by-default-memory-infra'];
+ config.chromeHighOverheadCategoriesSelected =
+ ['disabled-by-default-memory-infra'];
const result =
TraceConfig.decode(genConfigProto(config, {os: 'C', name: 'Chrome'}));
const sources = assertExists(result.dataSources);
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index 5a07355..fefb2ae 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -19,10 +19,10 @@
} from '../common/actions';
import {cacheTrace} from '../common/cache_manager';
import {TRACE_MARGIN_TIME_S} from '../common/constants';
-import {Engine, QueryError} from '../common/engine';
+import {Engine} from '../common/engine';
import {featureFlags, Flag} from '../common/feature_flags';
import {HttpRpcEngine} from '../common/http_rpc_engine';
-import {NUM, NUM_NULL, STR, STR_NULL} from '../common/query_result';
+import {NUM, NUM_NULL, QueryError, STR, STR_NULL} from '../common/query_result';
import {EngineMode} from '../common/state';
import {TimeSpan, toNs, toNsCeil, toNsFloor} from '../common/time';
import {resetEngineWorker, WasmEngineProxy} from '../common/wasm_engine_proxy';
@@ -507,6 +507,7 @@
inner join thread_track on slice.track_id = thread_track.id
group by bucket, utid
) using(utid)
+ where upid is not null
group by bucket, upid`);
const slicesData: {[key: string]: QuantizedLoad[]} = {};
diff --git a/ui/src/frontend/record_page.ts b/ui/src/frontend/record_page.ts
index 548db2a..7b957d9 100644
--- a/ui/src/frontend/record_page.ts
+++ b/ui/src/frontend/record_page.ts
@@ -721,35 +721,40 @@
categories = getBuiltinChromeCategoryList();
}
- // Show "disabled-by-default" categories last.
- const categoriesMap = new Map<string, string>();
+ const defaultCategories = new Map<string, string>();
+ const disabledByDefaultCategories = new Map<string, string>();
const disabledPrefix = 'disabled-by-default-';
- const overheadSuffix = '(high overhead)';
categories.forEach(cat => {
if (cat.startsWith(disabledPrefix)) {
- categoriesMap.set(
- cat, `${cat.replace(disabledPrefix, '')} ${overheadSuffix}`);
+ disabledByDefaultCategories.set(cat, cat.replace(disabledPrefix, ''));
} else {
- categoriesMap.set(cat, cat);
+ defaultCategories.set(cat, cat);
}
});
- return m(Dropdown, {
- title: 'Additional Chrome categories',
- cssClass: '.multicolumn.two-columns',
- options: categoriesMap,
- set: (cfg, val) => cfg.chromeCategoriesSelected = val,
- get: (cfg) => cfg.chromeCategoriesSelected,
- sort: (a, b) => {
- const aIsDisabled = a.includes(overheadSuffix);
- const bIsDisabled = b.includes(overheadSuffix);
- if (aIsDisabled === bIsDisabled) {
- return a.localeCompare(b);
- } else {
- return Number(aIsDisabled) - Number(bIsDisabled);
- }
- },
- } as DropdownAttrs);
+ return m(
+ 'div',
+ m(Dropdown, {
+ cssClass: '.singlecolumn',
+ title: 'Additional Chrome categories',
+ options: defaultCategories,
+ set: (cfg, val) => cfg.chromeCategoriesSelected = val,
+ get: (cfg) => cfg.chromeCategoriesSelected,
+ sort: (a, b) => {
+ return a.localeCompare(b);
+ },
+ } as DropdownAttrs),
+ m(Dropdown, {
+ cssClass: '.singlecolumn',
+ title: 'Additional high overhead Chrome categories',
+ options: disabledByDefaultCategories,
+ set: (cfg, val) => cfg.chromeHighOverheadCategoriesSelected = val,
+ get: (cfg) => cfg.chromeHighOverheadCategoriesSelected,
+ sort: (a, b) => {
+ return a.localeCompare(b);
+ },
+ } as DropdownAttrs),
+ );
}
function AdvancedSettings(cssClass: string) {
diff --git a/ui/src/tracks/cpu_profile/frontend.ts b/ui/src/tracks/cpu_profile/frontend.ts
index d156021..50b0361 100644
--- a/ui/src/tracks/cpu_profile/frontend.ts
+++ b/ui/src/tracks/cpu_profile/frontend.ts
@@ -25,6 +25,7 @@
import {Config, CPU_PROFILE_TRACK_KIND, Data} from './common';
+const BAR_HEIGHT = 3;
const MARGIN_TOP = 4.5;
const RECT_HEIGHT = 30.5;
@@ -38,8 +39,8 @@
return new CpuProfileTrack(args);
}
- private centerY = this.getHeight() / 2;
- private markerWidth = (this.getHeight() - MARGIN_TOP) / 2;
+ private centerY = this.getHeight() / 2 + BAR_HEIGHT;
+ private markerWidth = (this.getHeight() - MARGIN_TOP - BAR_HEIGHT) / 2;
private hoveredTs: number|undefined = undefined;
constructor(args: NewTrackArgs) {
@@ -73,6 +74,26 @@
strokeWidth,
data.callsiteId[i]);
}
+
+ let startX = data.tsStarts.length ? data.tsStarts[0] : -1;
+ let endX = data.tsStarts.length ? data.tsStarts[0] : -1;
+ let lastCallsiteId = data.callsiteId.length ? data.callsiteId[0] : -1;
+ for (let i = 0; i < data.tsStarts.length; i++) {
+ const centerX = data.tsStarts[i];
+ const callsiteId = data.callsiteId[i];
+ if (lastCallsiteId !== callsiteId) {
+ if (startX !== endX) {
+ const leftPx = timeScale.timeToPx(fromNs(startX)) - this.markerWidth;
+ const rightPx = timeScale.timeToPx(fromNs(endX)) + this.markerWidth;
+ const width = rightPx - leftPx;
+ ctx.fillStyle = colorForSample(lastCallsiteId, false);
+ ctx.fillRect(leftPx, MARGIN_TOP, width, BAR_HEIGHT);
+ }
+ startX = centerX;
+ }
+ endX = centerX;
+ lastCallsiteId = callsiteId;
+ }
}
drawMarker(