ui: switch UI to use track id instead of ref/ref_type
This CL changes the UI to consistently use track_id instead of
ref/ref_type when making queries on the counter tables.
This improves the performance of the worst performing tracks (the cpu
frequency track) by 2.5-3x (from 250-300ms to 100-150ms).
Change-Id: Ifb53c6c0262c8ddec7bc3a56e4690749746e5be7
diff --git a/src/trace_processor/span_join_operator_table.cc b/src/trace_processor/span_join_operator_table.cc
index 931289c..94c8ac1 100644
--- a/src/trace_processor/span_join_operator_table.cc
+++ b/src/trace_processor/span_join_operator_table.cc
@@ -169,8 +169,14 @@
return std::unique_ptr<SpanJoinOperatorTable::Cursor>(new Cursor(this, db_));
}
-int SpanJoinOperatorTable::BestIndex(const QueryConstraints&, BestIndexInfo*) {
+int SpanJoinOperatorTable::BestIndex(const QueryConstraints& qc,
+ BestIndexInfo* info) {
// TODO(lalitm): figure out cost estimation.
+ const auto& ob = qc.order_by();
+ if (ob.size() == 1 && ob.front().iColumn == Column::kTimestamp &&
+ !ob.front().desc) {
+ info->sqlite_omit_order_by = true;
+ }
return SQLITE_OK;
}
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index 7edcbba..8c5fb67 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -302,7 +302,8 @@
//}
const maxCpuFreq = await engine.query(`
select max(value)
- from counters
+ from counter c
+ inner join cpu_counter_track t on c.track_id = t.id
where name = 'cpufreq';
`);
@@ -325,13 +326,28 @@
// cpu freq data.
// TODO(taylori): Find a way to display cpu idle
// events even if there are no cpu freq events.
- const freqExists = await engine.query(`
- select value
- from counters
- where name = 'cpufreq' and ref = ${cpu}
+ const cpuFreqIdle = await engine.query(`
+ select
+ id as cpu_freq_id,
+ (
+ select id
+ from cpu_counter_track
+ where name = 'cpuidle'
+ and cpu = ${cpu}
+ limit 1
+ ) as cpu_idle_id
+ from cpu_counter_track
+ where name = 'cpufreq' and cpu = ${cpu}
limit 1;
`);
- if (freqExists.numRecords > 0) {
+ if (cpuFreqIdle.numRecords > 0) {
+ const freqTrackId = +cpuFreqIdle.columns[0].longValues![0];
+
+ const idleTrackExists: boolean = !cpuFreqIdle.columns[1].isNulls![0];
+ const idleTrackId = idleTrackExists ?
+ +cpuFreqIdle.columns[1].longValues![0] :
+ undefined;
+
tracksToAdd.push({
engineId: this.engineId,
kind: CPU_FREQ_TRACK_KIND,
@@ -340,6 +356,8 @@
config: {
cpu,
maximumValue: +maxCpuFreq.columns[0].doubleValues![0],
+ freqTrackId,
+ idleTrackId,
}
});
}
@@ -414,46 +432,69 @@
}
}
-
- const counters = await engine.query(`
- select name, ref, ref_type
- from counter_definitions
- where ref is not null
- group by name, ref, ref_type
- order by ref_type desc
+ // Add global or GPU counter tracks that are not bound to any pid/tid.
+ const globalCounters = await engine.query(`
+ select name, id
+ from counter_track
+ where type = 'counter_track'
+ union
+ select name, id
+ from gpu_counter_track
+ where name != 'gpufreq'
`);
-
- interface CounterMap {
- [index: number]: string[];
+ for (let i = 0; i < globalCounters.numRecords; i++) {
+ const name = globalCounters.columns[0].stringValues![i];
+ const trackId = +globalCounters.columns[1].longValues![i];
+ tracksToAdd.push({
+ engineId: this.engineId,
+ kind: 'CounterTrack',
+ name,
+ trackGroup: SCROLLING_TRACK_GROUP,
+ config: {
+ name,
+ trackId,
+ }
+ });
}
- const counterUpids: CounterMap = new Array();
- const counterUtids: CounterMap = new Array();
- for (let i = 0; i < counters.numRecords; i++) {
- const name = counters.columns[0].stringValues![i];
- const ref = +counters.columns[1].longValues![i];
- const refType = counters.columns[2].stringValues![i];
- if (refType === 'upid') {
- const el = counterUpids[ref];
- el === undefined ? counterUpids[ref] = [name] :
- counterUpids[ref].push(name);
- } else if (refType === 'utid') {
- const el = counterUtids[ref];
- el === undefined ? counterUtids[ref] = [name] :
- counterUtids[ref].push(name);
- } else if (
- refType === '[NULL]' || (refType === 'gpu' && name !== 'gpufreq')) {
- // Add global or GPU counter tracks that are not bound to any pid/tid.
- tracksToAdd.push({
- engineId: this.engineId,
- kind: 'CounterTrack',
- name,
- trackGroup: SCROLLING_TRACK_GROUP,
- config: {
- name,
- ref: 0,
- }
- });
+ interface CounterTrack {
+ name: string;
+ trackId: number;
+ }
+
+ const counterUtids = new Map<number, CounterTrack[]>();
+ const threadCounters = await engine.query(`
+ select name, utid, id
+ from thread_counter_track
+ `);
+ for (let i = 0; i < threadCounters.numRecords; i++) {
+ const name = threadCounters.columns[0].stringValues![i];
+ const utid = +threadCounters.columns[1].longValues![i];
+ const trackId = +threadCounters.columns[2].longValues![i];
+
+ const el = counterUtids.get(utid);
+ if (el === undefined) {
+ counterUtids.set(utid, [{name, trackId}]);
+ } else {
+ el.push({name, trackId});
+ }
+ }
+
+ const counterUpids = new Map<number, CounterTrack[]>();
+ const processCounters = await engine.query(`
+ select name, upid, id
+ from process_counter_track
+ `);
+ for (let i = 0; i < processCounters.numRecords; i++) {
+ const name = processCounters.columns[0].stringValues![i];
+ const upid = +processCounters.columns[1].longValues![i];
+ const trackId = +processCounters.columns[2].longValues![i];
+
+ const el = counterUpids.get(upid);
+ if (el === undefined) {
+ counterUpids.set(upid, [{name, trackId}]);
+ } else {
+ el.push({name, trackId});
}
}
@@ -526,8 +567,8 @@
const threadTrack =
utid === null ? undefined : utidToThreadTrack.get(utid);
if (threadTrack === undefined &&
- (upid === null || counterUpids[upid] === undefined) &&
- counterUtids[utid] === undefined && !threadHasSched &&
+ (upid === null || counterUpids.get(upid) === undefined) &&
+ counterUtids.get(utid) === undefined && !threadHasSched &&
(upid === null || upid !== null && !heapUpids.has(upid))) {
continue;
}
@@ -571,18 +612,15 @@
}));
if (upid !== null) {
- const counterNames = counterUpids[upid];
+ const counterNames = counterUpids.get(upid);
if (counterNames !== undefined) {
counterNames.forEach(element => {
tracksToAdd.push({
engineId: this.engineId,
kind: 'CounterTrack',
- name: element,
+ name: element.name,
trackGroup: pUuid,
- config: {
- name: element,
- ref: upid,
- }
+ config: {name: element.name, trackId: element.trackId}
});
});
}
@@ -612,17 +650,17 @@
}
}
}
- const counterThreadNames = counterUtids[utid];
+ const counterThreadNames = counterUtids.get(utid);
if (counterThreadNames !== undefined) {
counterThreadNames.forEach(element => {
tracksToAdd.push({
engineId: this.engineId,
kind: 'CounterTrack',
- name: element,
+ name: element.name,
trackGroup: pUuid,
config: {
- name: element,
- ref: utid,
+ name: element.name,
+ trackId: element.trackId,
}
});
});
diff --git a/ui/src/tracks/counter/common.ts b/ui/src/tracks/counter/common.ts
index 0eb6dfb..53a603d 100644
--- a/ui/src/tracks/counter/common.ts
+++ b/ui/src/tracks/counter/common.ts
@@ -30,6 +30,6 @@
name: string;
maximumValue?: number;
minimumValue?: number;
- ref: number;
+ trackId: number;
scale?: 'DEFAULT'|'RELATIVE';
}
diff --git a/ui/src/tracks/counter/controller.ts b/ui/src/tracks/counter/controller.ts
index 4085845..0be0371 100644
--- a/ui/src/tracks/counter/controller.ts
+++ b/ui/src/tracks/counter/controller.ts
@@ -39,20 +39,22 @@
if (!this.setup) {
const result = await this.query(`
- select max(value), min(value) from
- counters where name = '${this.config.name}'
- and ref = ${this.config.ref}`);
+ select max(value), min(value)
+ from counter
+ where track_id = ${this.config.trackId}`);
this.maximumValueSeen = +result.columns[0].doubleValues![0];
this.minimumValueSeen = +result.columns[1].doubleValues![0];
await this.query(
`create virtual table ${this.tableName('window')} using window;`);
- await this.query(`create view ${this.tableName('counter_view')} as
- select ts,
- lead(ts, 1, ts) over (partition by ref_type order by ts) - ts as dur,
- value, name, ref
- from counters
- where name = '${this.config.name}' and ref = ${this.config.ref};`);
+ await this.query(`
+ create view ${this.tableName('counter_view')} as
+ select
+ ts,
+ lead(ts, 1, ts) over (order by ts) - ts as dur,
+ value
+ from counter
+ where track_id = ${this.config.trackId};`);
await this.query(`create virtual table ${this.tableName('span')} using
span_join(${this.tableName('counter_view')},
@@ -60,13 +62,16 @@
this.setup = true;
}
- const result = await this.engine.queryOneRow(`select count(*)
- from (select
- ts,
- lead(ts, 1, ts) over (partition by ref_type order by ts) as ts_end,
- from counters
- where name = '${this.config.name}' and ref = ${this.config.ref})
- where ts <= ${endNs} and ${startNs} <= ts_end`);
+ const result = await this.engine.queryOneRow(`
+ select count(*)
+ from (
+ select
+ ts,
+ lead(ts, 1, ts) over (order by ts) as ts_end,
+ from counter
+ where track_id = ${this.config.trackId}
+ )
+ where ts <= ${endNs} and ${startNs} <= ts_end`);
// Only quantize if we have too much data to draw.
const isQuantized = result[0] > LIMIT;
@@ -94,18 +99,32 @@
// Union that with the query that finds all the counters within
// the current query range.
query = `
- select * from (select ts, value, counter_id from counters
- where name = '${this.config.name}' and ref = ${this.config.ref} and
- ts <= ${startNs} order by ts desc limit 1)
- UNION
- select * from (select ts, value, counter_id
- from (select
- ts,
- lead(ts, 1, ts) over (partition by ref_type order by ts) as ts_end,
- value, counter_id
- from counters
- where name = '${this.config.name}' and ref = ${this.config.ref})
- where ts <= ${endNs} and ${startNs} <= ts_end limit ${LIMIT});`;
+ select *
+ from (
+ select ts, value, track_id
+ from counter
+ where
+ track_id = ${this.config.trackId} and
+ ts <= ${startNs}
+ order by ts desc
+ limit 1
+ )
+ union
+ select *
+ from (
+ select ts, value, track_id
+ from (
+ select
+ ts,
+ lead(ts, 1, ts) over (order by ts) as ts_end,
+ value,
+ track_id
+ from counter
+ where track_id = ${this.config.trackId}
+ )
+ where ts <= ${endNs} and ${startNs} <= ts_end
+ limit ${LIMIT}
+ );`;
}
const rawResult = await this.query(query);
diff --git a/ui/src/tracks/cpu_freq/common.ts b/ui/src/tracks/cpu_freq/common.ts
index 8968907..fff0c8f 100644
--- a/ui/src/tracks/cpu_freq/common.ts
+++ b/ui/src/tracks/cpu_freq/common.ts
@@ -28,5 +28,8 @@
export interface Config {
cpu: number;
+ freqTrackId: number;
+ idleTrackId?: number;
maximumValue?: number;
- minimumValue?: number;}
+ minimumValue?: number;
+}
diff --git a/ui/src/tracks/cpu_freq/controller.ts b/ui/src/tracks/cpu_freq/controller.ts
index 190a3d9..bdfbdae 100644
--- a/ui/src/tracks/cpu_freq/controller.ts
+++ b/ui/src/tracks/cpu_freq/controller.ts
@@ -38,9 +38,9 @@
if (!this.setup) {
const result = await this.query(`
- select max(value) from
- counters where name = 'cpufreq'
- and ref = ${this.config.cpu}`);
+ select max(value)
+ from counter
+ where track_id = ${this.config.freqTrackId}`);
this.maximumValueSeen = +result.columns[0].doubleValues![0];
await this.query(
@@ -49,36 +49,39 @@
await this.query(`create view ${this.tableName('freq')}
as select
ts,
- lead(ts) over (order by ts) - ts as dur,
- ref as cpu,
- name as freq_name,
+ lead(ts) over () - ts as dur,
value as freq_value
- from counters
- where name = 'cpufreq'
- and ref = ${this.config.cpu}
- and ref_type = 'cpu';
+ from counter c
+ where track_id = ${this.config.freqTrackId};
`);
- await this.query(`create view ${this.tableName('idle')}
- as select
- ts,
- lead(ts) over (order by ts) - ts as dur,
- ref as cpu,
- name as idle_name,
- value as idle_value
- from counters
- where name = 'cpuidle'
- and ref = ${this.config.cpu}
- and ref_type = 'cpu';
- `);
+ // If there is no idle track, just make the idle track a single row
+ // which spans the entire time range.
+ if (this.config.idleTrackId === undefined) {
+ await this.query(`create view ${this.tableName('idle')} as
+ select
+ 0 as ts,
+ ${Number.MAX_SAFE_INTEGER} as dur,
+ -1 as idle_value;
+ `);
+ } else {
+ await this.query(`create view ${this.tableName('idle')}
+ as select
+ ts,
+ lead(ts) over () - ts as dur,
+ value as idle_value
+ from counter c
+ where track_id = ${this.config.idleTrackId};
+ `);
+ }
await this.query(`create virtual table ${this.tableName('freq_idle')}
- using span_join(${this.tableName('freq')} PARTITIONED cpu,
- ${this.tableName('idle')} PARTITIONED cpu);`);
+ using span_join(${this.tableName('freq')},
+ ${this.tableName('idle')});`);
await this.query(`create virtual table ${this.tableName('span_activity')}
- using span_join(${this.tableName('freq_idle')} PARTITIONED cpu,
- ${this.tableName('window')});`);
+ using span_join(${this.tableName('freq_idle')},
+ ${this.tableName('window')});`);
// TODO(taylori): Move the idle value processing to the TP.
await this.query(`create view ${this.tableName('activity')}
@@ -86,7 +89,6 @@
ts,
dur,
quantum_ts,
- cpu,
case idle_value
when 4294967295 then -1
else idle_value