Skip to content

Commit

Permalink
Merge "ui: Don't force tracks to always create views" into main
Browse files Browse the repository at this point in the history
  • Loading branch information
chromy authored and Gerrit Code Review committed Oct 19, 2023
2 parents 34f1b98 + 12ebaf4 commit 1a56a11
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 48 deletions.
3 changes: 3 additions & 0 deletions ui/src/base/disposable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ export class DisposableCallback implements Disposable {
}
}

export class NullDisposable implements Disposable {
dispose() {}
}

// A collection of Disposables.
// Disposables can be added one by one, (e.g. during the lifecycle of a
Expand Down
50 changes: 35 additions & 15 deletions ui/src/frontend/base_slice_track.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import {Disposable, NullDisposable} from '../base/disposable';
import {assertExists} from '../base/logging';
import {
duration,
Expand Down Expand Up @@ -144,12 +145,14 @@ export const filterVisibleSlicesForTesting = filterVisibleSlices;
// If you need temporally overlapping slices, look at AsyncSliceTrack, which
// merges several tracks into one visual track.
export const BASE_SLICE_ROW = {
id: NUM, // The slice ID, for selection / lookups.
id: NUM, // The slice ID, for selection / lookups.
ts: LONG, // Start time in nanoseconds.
dur: LONG, // Duration in nanoseconds. -1 = incomplete, 0 = instant.
depth: NUM, // Vertical depth.

// These are computed by the base class:
tsq: LONG, // Quantized |ts|. This class owns the quantization logic.
tsqEnd: LONG, // Quantized |ts+dur|. The end bucket.
ts: LONG, // Start time in nanoseconds.
dur: LONG, // Duration in nanoseconds. -1 = incomplete, 0 = instant.
depth: NUM, // Vertical depth.
};

export type BaseSliceRow = typeof BASE_SLICE_ROW;
Expand Down Expand Up @@ -203,7 +206,6 @@ export abstract class BaseSliceTrack<T extends BaseSliceTrackTypes =
// than just remembering it when we see it.
private selectedSlice?: CastInternal<T['slice']>;

protected readonly tableName: string;
private maxDurNs: duration = 0n;

private sqlState: 'UNINITIALIZED'|'INITIALIZING'|'QUERY_PENDING'|
Expand All @@ -227,11 +229,30 @@ export abstract class BaseSliceTrack<T extends BaseSliceTrackTypes =
// TODO(hjd): Replace once we have cancellable query sequences.
private isDestroyed = false;

// Cleanup hook for onInit.
private initState?: Disposable;

// Extension points.
// Each extension point should take a dedicated argument type (e.g.,
// OnSliceOverArgs {slice?: T['slice']}) so it makes future extensions
// non-API-breaking (e.g. if we want to add the X position).
abstract initSqlTable(_tableName: string): Promise<void>;

// onInit hook lets you do asynchronous set up e.g. creating a table
// etc. We guarantee that this will be resolved before doing any
// queries using the result of getSqlSource(). All persistent
// state in trace_processor should be cleaned up when dispose is
// called on the returned hook. In the common case of where
// the data for this track is d
async onInit(): Promise<Disposable> {
return new NullDisposable();
}

// This should be an SQL expression returning all the columns listed
// metioned by getRowSpec() exluding tsq and tsqEnd.
// For example you might return an SQL expression of the form:
// `select id, ts, dur, 0 as depth from foo where bar = 'baz'`
abstract getSqlSource(): string;

getRowSpec(): T['row'] {
return BASE_SLICE_ROW;
}
Expand All @@ -256,10 +277,6 @@ export abstract class BaseSliceTrack<T extends BaseSliceTrackTypes =

constructor(args: NewTrackArgs) {
super(args);
// TODO(hjd): Handle pinned tracks, which current cause a crash
// since the tableName we generate is the same for both.
this.tableName = `track_${this.trackId}`.replace(/[^a-zA-Z0-9_]+/g, '_');

// Work out the extra columns.
// This is the union of the embedder-defined columns and the base columns
// we know about (ts, dur, ...).
Expand Down Expand Up @@ -507,7 +524,10 @@ export abstract class BaseSliceTrack<T extends BaseSliceTrackTypes =
onDestroy() {
super.onDestroy();
this.isDestroyed = true;
this.engine.query(`DROP VIEW IF EXISTS ${this.tableName}`);
if (this.initState) {
this.initState.dispose();
this.initState = undefined;
}
}

// This method figures out if the visible window is outside the bounds of
Expand All @@ -522,14 +542,14 @@ export abstract class BaseSliceTrack<T extends BaseSliceTrackTypes =
if (this.isDestroyed) {
return;
}
await this.initSqlTable(this.tableName);
this.initState = await this.onInit();

if (this.isDestroyed) {
return;
}
const queryRes = await this.engine.query(`select
ifnull(max(dur), 0) as maxDur, count(1) as rowCount
from ${this.tableName}`);
from (${this.getSqlSource()})`);
const row = queryRes.firstRow({maxDur: LONG, rowCount: NUM});
this.maxDurNs = row.maxDur;

Expand Down Expand Up @@ -562,7 +582,7 @@ export abstract class BaseSliceTrack<T extends BaseSliceTrackTypes =
id,
${this.depthColumn()}
${extraCols ? ',' + extraCols : ''}
from ${this.tableName}
from (${this.getSqlSource()})
where dur = -1;
`);
const incomplete =
Expand Down Expand Up @@ -649,7 +669,7 @@ export abstract class BaseSliceTrack<T extends BaseSliceTrackTypes =
id,
${this.depthColumn()}
${extraCols ? ',' + extraCols : ''}
FROM ${this.tableName} ${constraint}
FROM (${this.getSqlSource()}) ${constraint}
`);

// Here convert each row to a Slice. We do what we can do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,14 @@ export class ChromeTasksScrollJankTrack extends
return new ChromeTasksScrollJankTrack(args);
}

async initSqlTable(tableName: string) {
await this.engine.query(`
create view ${tableName} as
select s2.ts, s2.dur, s2.id, 0 as depth, s1.full_name as name
constructor(args: NewTrackArgs) {
super(args);
}

getSqlSource(): string {
return `select s2.ts as ts, s2.dur as dur, s2.id as id, 0 as depth, s1.full_name as name
from chrome_tasks_delaying_input_processing s1
join slice s2 on s2.id=s1.slice_id
`);
join slice s2 on s2.id=s1.slice_id`;
}
}
export type GetTrackGroupUuidFn = (utid: number, upid: number|null) => string;
Expand Down
7 changes: 2 additions & 5 deletions ui/src/tracks/chrome_scroll_jank/event_latency_track.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,8 @@ export class EventLatencyTrack extends
ScrollJankPluginState.getInstance().unregisterTrack(EventLatencyTrack.kind);
}

async initSqlTable(tableName: string) {
const sql =
`CREATE VIEW ${tableName} AS SELECT * FROM ${this.config.baseTable}`;

await this.engine.query(sql);
getSqlSource(): string {
return `SELECT * FROM ${this.config.baseTable}`;
}

getDetailsPanel(): CustomSqlDetailsPanelConfig {
Expand Down
6 changes: 2 additions & 4 deletions ui/src/tracks/chrome_slices/generic_slice_track.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,8 @@ export class GenericSliceTrack extends NamedSliceTrack<GenericSliceTrackTypes> {
super(args);
}

async initSqlTable(tableName: string): Promise<void> {
const sql = `create view ${tableName} as
select ts, dur, id, depth, ifnull(name, '') as name
getSqlSource(): string {
return `select ts, dur, id, depth, ifnull(name, '') as name
from slice where track_id = ${this.config.sqlTrackId}`;
await this.engine.query(sql);
}
}
30 changes: 21 additions & 9 deletions ui/src/tracks/custom_sql_table_slices/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import {Disposable, DisposableCallback} from '../../base/disposable';
import {Actions} from '../../common/actions';
import {
generateSqlWithInternalLayout,
Expand Down Expand Up @@ -46,31 +47,42 @@ export interface CustomSqlDetailsPanelConfig {

export abstract class CustomSqlTableSliceTrack<
T extends NamedSliceTrackTypes> extends NamedSliceTrack<T> {
protected readonly tableName;

constructor(args: NewTrackArgs) {
super(args);
this.tableName = `customsqltableslicetrack_{uuidv4()}`;
}

abstract getSqlDataSource(): CustomSqlTableDefConfig;

// Override by subclasses.
abstract getDetailsPanel(): CustomSqlDetailsPanelConfig;

async initSqlTable(tableName: string) {

async onInit(): Promise<Disposable> {
const config = this.getSqlDataSource();
let columns = ['*'];
if (config.columns !== undefined) {
columns = config.columns;
}

const sql = `CREATE VIEW ${tableName} AS ` + generateSqlWithInternalLayout({
columns: columns,
sourceTable: config.sqlTableName,
ts: 'ts',
dur: 'dur',
whereClause: config.whereClause,
});

const sql =
`CREATE VIEW ${this.tableName} AS ` + generateSqlWithInternalLayout({
columns: columns,
sourceTable: config.sqlTableName,
ts: 'ts',
dur: 'dur',
whereClause: config.whereClause,
});
await this.engine.query(sql);
return DisposableCallback.from(() => {
this.engine.query(`DROP VIEW ${this.tableName}`);
});
}

getSqlSource(): string {
return `SELECT * FROM ${this.tableName}`;
}

isSelectionHandled(selection: Selection) {
Expand Down
5 changes: 3 additions & 2 deletions ui/src/tracks/debug/slice_track.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import m from 'mithril';

import {Disposable} from '../../base/disposable';
import {Actions, DEBUG_SLICE_TRACK_KIND} from '../../common/actions';
import {EngineProxy} from '../../common/engine';
import {SCROLLING_TRACK_GROUP} from '../../common/state';
Expand Down Expand Up @@ -77,8 +78,8 @@ export class DebugTrackV2 extends CustomSqlTableSliceTrack<DebugTrackV2Types> {
};
}

async initSqlTable(tableName: string): Promise<void> {
super.initSqlTable(tableName);
async onInit(): Promise<Disposable> {
return super.onInit();
}

getTrackShellButtons(): m.Children {
Expand Down
5 changes: 2 additions & 3 deletions ui/src/tracks/thread_state/thread_state_track_v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,9 @@ export class ThreadStateTrack extends BaseSliceTrack<ThreadStateTrackTypes> {
return THREAD_STATE_ROW;
}

async initSqlTable(tableName: string): Promise<void> {
getSqlSource(): string {
// Do not display states 'x' and 'S' (dead & sleeping).
const sql = `
create view ${tableName} as
select
id,
ts,
Expand All @@ -81,7 +80,7 @@ export class ThreadStateTrack extends BaseSliceTrack<ThreadStateTrackTypes> {
state != 'x' and
state != 'S'
`;
await this.engine.query(sql);
return sql;
}

rowToSlice(row: ThreadStateTrackTypes['row']):
Expand Down
6 changes: 2 additions & 4 deletions ui/src/tracks/thread_state/thread_state_v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,9 @@ export class ThreadStateTrack extends BaseSliceTrack<ThreadStateTrackTypes> {
return THREAD_STATE_ROW;
}

async initSqlTable(tableName: string): Promise<void> {
getSqlSource(): string {
// Do not display states 'x' and 'S' (dead & sleeping).
const sql = `
create view ${tableName} as
return `
select
id,
ts,
Expand All @@ -83,7 +82,6 @@ export class ThreadStateTrack extends BaseSliceTrack<ThreadStateTrackTypes> {
state != 'x' and
state != 'S'
`;
await this.engine.query(sql);
}

rowToSlice(row: ThreadStateTrackTypes['row']):
Expand Down

0 comments on commit 1a56a11

Please sign in to comment.