diff --git a/ui/src/frontend/thread_state_tab.ts b/ui/src/frontend/thread_state_tab.ts index 3aedd4b52d..c68530e81a 100644 --- a/ui/src/frontend/thread_state_tab.ts +++ b/ui/src/frontend/thread_state_tab.ts @@ -230,6 +230,43 @@ export class ThreadStateTab extends BottomTab { name, }); const sliceColumns = {ts: 'ts', dur: 'dur', name: 'thread_name'}; + const sliceSliceColumns = {ts: 'ts', dur: 'dur', name: 'slice_name'}; + const sliceColumnNames = [ + 'ts', + 'dur', + 'id', + 'utid', + 'thread_name', + 'process_name', + 'height', + 'table_name', + ]; + + const sliceColumnThreadStateNames = [ + 'ts', + 'dur', + 'id', + 'utid', + 'thread_name', + 'process_name', + 'state', + 'blocked_function', + 'height', + 'table_name' + ]; + + const sliceColumnSliceNames = [ + 'ts', + 'dur', + 'id', + 'utid', + 'thread_name', + 'process_name', + 'slice_name', + 'slice_depth', + 'height', + 'table_name', + ]; const nameForNextOrPrev = (state: ThreadState) => `${state.state} for ${Duration.humanise(state.dur)}`; @@ -277,15 +314,54 @@ export class ThreadStateTab extends BottomTab { { sqlSource: ` - SELECT ts, dur, thread_name, process_name, height + SELECT ts, dur, id, utid, thread_name, process_name, height, + "thread_state" AS table_name FROM experimental_thread_executing_span_critical_path( NULL, ${this.state?.thread?.utid}) `, - columns: ['ts', 'dur', 'thread_name', 'process_name', 'height'], + columns: sliceColumnNames, }, `${this.state?.thread?.name}`, sliceColumns, - ['ts', 'dur', 'thread_name', 'process_name', 'height'])), + sliceColumnNames)), + }, + ), m(Button, + { + label: 'Critical path thread states', + onclick: () => runQuery(`SELECT IMPORT('experimental.thread_executing_span');`, this.engine) + .then(() => addDebugTrack( + this.engine, + { + sqlSource: + ` + SELECT ts, dur, thread_state_id AS id, utid, thread_name, process_name, state, blocked_function, height, + "thread_state" AS table_name + FROM experimental_thread_executing_span_critical_path_thread_states(${this.state?.thread?.utid}) + `, + columns: sliceColumnThreadStateNames, + }, + `${this.state?.thread?.name}`, + sliceColumns, + sliceColumnThreadStateNames)), + }, + ), m(Button, + { + label: 'Critical path slices', + onclick: () => runQuery(`SELECT IMPORT('experimental.thread_executing_span');`, this.engine) + .then(() => addDebugTrack( + this.engine, + { + sqlSource: + ` + SELECT ts, dur, slice_id AS id, utid, thread_name, process_name, slice_name, slice_depth, height, + "slice" AS table_name + FROM experimental_thread_executing_span_critical_path_slices(${this.state?.thread?.utid}) + `, + columns: sliceColumnSliceNames, + }, + `${this.state?.thread?.name}`, + sliceSliceColumns, + sliceColumnSliceNames)), }, )]; } diff --git a/ui/src/tracks/debug/details_tab.ts b/ui/src/tracks/debug/details_tab.ts index 3ca1882c79..1e850acd93 100644 --- a/ui/src/tracks/debug/details_tab.ts +++ b/ui/src/tracks/debug/details_tab.ts @@ -101,15 +101,16 @@ export class DebugSliceDetailsTab extends } private async maybeLoadThreadState( - id: number|undefined, ts: time, dur: duration, + id: number|undefined, ts: time, dur: duration, table: string|undefined, utid?: Utid): Promise { if (id === undefined) return undefined; if (utid === undefined) return undefined; const threadState = await getThreadState(this.engine, id); if (threadState === undefined) return undefined; - if (threadState.ts === ts && threadState.dur === dur && - threadState.thread?.utid === utid) { + if ((table === 'thread_state') || + (threadState.ts === ts && threadState.dur === dur && + threadState.thread?.utid === utid)) { return threadState; } else { return undefined; @@ -132,15 +133,16 @@ export class DebugSliceDetailsTab extends } private async maybeLoadSlice( - id: number|undefined, ts: time, dur: duration, + id: number|undefined, ts: time, dur: duration, table: string|undefined, sqlTrackId?: number): Promise { if (id === undefined) return undefined; - if (sqlTrackId === undefined) return undefined; + if ((table !== 'slice') && sqlTrackId === undefined) return undefined; const slice = await getSlice(this.engine, asSliceSqlId(id)); if (slice === undefined) return undefined; - if (slice.ts === ts && slice.dur === dur && - slice.sqlTrackId === sqlTrackId) { + if ((table === 'slice') || + (slice.ts === ts && slice.dur === dur && + slice.sqlTrackId === sqlTrackId)) { return slice; } else { return undefined; @@ -189,6 +191,7 @@ export class DebugSliceDetailsTab extends sqlValueToNumber(this.data.args['id']), this.data.ts, this.data.dur, + sqlValueToString(this.data.args['table_name']), sqlValueToUtid(this.data.args['utid'])); this.slice = await this.maybeLoadSlice( @@ -196,6 +199,7 @@ export class DebugSliceDetailsTab extends sqlValueToNumber(this.data.args['slice_id']), this.data.ts, this.data.dur, + sqlValueToString(this.data.args['table_name']), sqlValueToNumber(this.data.args['track_id'])); raf.scheduleRedraw();