diff options
author | Lalit Maganti <lalitm@google.com> | 2024-04-26 15:28:20 +0100 |
---|---|---|
committer | Lalit Maganti <lalitm@google.com> | 2024-04-26 15:28:20 +0100 |
commit | 6e0ff97cfca7698faf1b029b1cf2082540087516 (patch) | |
tree | b28a75d31961e55d0b5dce59ad525206bb43372e | |
parent | 34582f5b87c886a55341f09544c43441da4b6f0a (diff) | |
download | perfetto-6e0ff97cfca7698faf1b029b1cf2082540087516.tar.gz |
ui: add tracks to list of searchable items
Change-Id: I128a0a04fb8714f51caa09ef8b749f5c74baae72
-rw-r--r-- | ui/src/common/search_data.ts | 8 | ||||
-rw-r--r-- | ui/src/controller/search_controller.ts | 143 | ||||
-rw-r--r-- | ui/src/frontend/globals.ts | 8 | ||||
-rw-r--r-- | ui/src/frontend/search_handler.ts | 111 | ||||
-rw-r--r-- | ui/src/frontend/tickmark_panel.ts | 28 |
5 files changed, 169 insertions, 129 deletions
diff --git a/ui/src/common/search_data.ts b/ui/src/common/search_data.ts index b81dfb227..7209c048f 100644 --- a/ui/src/common/search_data.ts +++ b/ui/src/common/search_data.ts @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +export type SearchSource = 'cpu' | 'log' | 'slice' | 'track'; + export interface SearchSummary { tsStarts: BigInt64Array; tsEnds: BigInt64Array; @@ -19,10 +21,10 @@ export interface SearchSummary { } export interface CurrentSearchResults { - sliceIds: Float64Array; - tsStarts: BigInt64Array; + eventIds: Float64Array; + tses: BigInt64Array; utids: Float64Array; trackKeys: string[]; - sources: string[]; + sources: SearchSource[]; totalResults: number; } diff --git a/ui/src/controller/search_controller.ts b/ui/src/controller/search_controller.ts index 5caff6ead..61ada9330 100644 --- a/ui/src/controller/search_controller.ts +++ b/ui/src/controller/search_controller.ts @@ -15,7 +15,11 @@ import {sqliteString} from '../base/string_utils'; import {Duration, duration, Span, time, Time, TimeSpan} from '../base/time'; import {exists} from '../base/utils'; -import {CurrentSearchResults, SearchSummary} from '../common/search_data'; +import { + CurrentSearchResults, + SearchSource, + SearchSummary, +} from '../common/search_data'; import {OmniboxState} from '../common/state'; import {globals} from '../frontend/globals'; import {publishSearch, publishSearchResult} from '../frontend/publish'; @@ -100,8 +104,8 @@ export class SearchController extends Controller<'main'> { count: new Uint8Array(0), }); publishSearchResult({ - sliceIds: new Float64Array(0), - tsStarts: new BigInt64Array(0), + eventIds: new Float64Array(0), + tses: new BigInt64Array(0), utids: new Float64Array(0), sources: [], trackKeys: [], @@ -203,11 +207,9 @@ export class SearchController extends Controller<'main'> { // easier once the track table has entries for all the tracks. const cpuToTrackId = new Map(); for (const track of Object.values(globals.state.tracks)) { - if (exists(track?.uri)) { - const trackInfo = globals.trackManager.resolveTrackInfo(track.uri); - if (trackInfo?.kind === CPU_SLICE_TRACK_KIND) { - exists(trackInfo.cpu) && cpuToTrackId.set(trackInfo.cpu, track.key); - } + const trackInfo = globals.trackManager.resolveTrackInfo(track.uri); + if (trackInfo?.kind === CPU_SLICE_TRACK_KIND) { + exists(trackInfo.cpu) && cpuToTrackId.set(trackInfo.cpu, track.key); } } @@ -220,60 +222,83 @@ export class SearchController extends Controller<'main'> { utids.push(it.utid); } - const queryRes = await this.query(` - select - id as sliceId, - ts, - 'cpu' as source, - cpu as sourceId, - utid - from sched where utid in (${utids.join(',')}) - union - select - slice_id as sliceId, - ts, - 'track' as source, - track_id as sourceId, - 0 as utid - from slice - where slice.name glob ${searchLiteral} - or ( - 0 != CAST(${sqliteString(search)} AS INT) and - sliceId = CAST(${sqliteString(search)} AS INT) - ) - union - select - slice_id as sliceId, - ts, - 'track' as source, - track_id as sourceId, - 0 as utid - from slice - join args using(arg_set_id) - where string_value glob ${searchLiteral} or key glob ${searchLiteral} - union - select - id as sliceId, - ts, - 'log' as source, - 0 as sourceId, - utid - from android_logs where msg glob ${searchLiteral} - order by ts - + const res = await this.query(` + select + id as sliceId, + ts, + 'cpu' as source, + cpu as sourceId, + utid + from sched where utid in (${utids.join(',')}) + union all + select * + from ( + select + slice_id as sliceId, + ts, + 'slice' as source, + track_id as sourceId, + 0 as utid + from slice + where slice.name glob ${searchLiteral} + or ( + 0 != CAST(${sqliteString(search)} AS INT) and + sliceId = CAST(${sqliteString(search)} AS INT) + ) + union + select + slice_id as sliceId, + ts, + 'slice' as source, + track_id as sourceId, + 0 as utid + from slice + join args using(arg_set_id) + where string_value glob ${searchLiteral} or key glob ${searchLiteral} + ) + union all + select + id as sliceId, + ts, + 'log' as source, + 0 as sourceId, + utid + from android_logs where msg glob ${searchLiteral} + order by ts `); - const rows = queryRes.numRows(); const searchResults: CurrentSearchResults = { - sliceIds: new Float64Array(rows), - tsStarts: new BigInt64Array(rows), - utids: new Float64Array(rows), - trackKeys: [], + eventIds: new Float64Array(0), + tses: new BigInt64Array(0), + utids: new Float64Array(0), sources: [], + trackKeys: [], totalResults: 0, }; - const it = queryRes.iter({ + const lowerSearch = search.toLowerCase(); + for (const track of Object.values(globals.state.tracks)) { + if (track.name.toLowerCase().indexOf(lowerSearch) === -1) { + continue; + } + searchResults.totalResults++; + searchResults.sources.push('track'); + searchResults.trackKeys.push(track.key); + } + + const rows = res.numRows(); + searchResults.eventIds = new Float64Array( + searchResults.totalResults + rows, + ); + searchResults.tses = new BigInt64Array(searchResults.totalResults + rows); + searchResults.utids = new Float64Array(searchResults.totalResults + rows); + for (let i = 0; i < searchResults.totalResults; ++i) { + searchResults.eventIds[i] = -1; + searchResults.tses[i] = -1n; + searchResults.utids[i] = -1; + } + + const it = res.iter({ sliceId: NUM, ts: LONG, source: STR, @@ -284,7 +309,7 @@ export class SearchController extends Controller<'main'> { let trackId = undefined; if (it.source === 'cpu') { trackId = cpuToTrackId.get(it.sourceId); - } else if (it.source === 'track') { + } else if (it.source === 'slice') { trackId = globals.trackManager.trackKeyByTrackId.get(it.sourceId); } else if (it.source === 'log') { const logTracks = Object.values(globals.state.tracks).filter( @@ -305,9 +330,9 @@ export class SearchController extends Controller<'main'> { const i = searchResults.totalResults++; searchResults.trackKeys.push(trackId); - searchResults.sources.push(it.source); - searchResults.sliceIds[i] = it.sliceId; - searchResults.tsStarts[i] = it.ts; + searchResults.sources.push(it.source as SearchSource); + searchResults.eventIds[i] = it.sliceId; + searchResults.tses[i] = it.ts; searchResults.utids[i] = it.utid; } return searchResults; diff --git a/ui/src/frontend/globals.ts b/ui/src/frontend/globals.ts index 8fc392d9e..68e16a559 100644 --- a/ui/src/frontend/globals.ts +++ b/ui/src/frontend/globals.ts @@ -276,8 +276,8 @@ class Globals { private _publishRedraw?: () => void = undefined; private _currentSearchResults: CurrentSearchResults = { - sliceIds: new Float64Array(0), - tsStarts: new BigInt64Array(0), + eventIds: new Float64Array(0), + tses: new BigInt64Array(0), utids: new Float64Array(0), trackKeys: [], sources: [], @@ -648,8 +648,8 @@ class Globals { this._numQueriesQueued = 0; this._metricResult = undefined; this._currentSearchResults = { - sliceIds: new Float64Array(0), - tsStarts: new BigInt64Array(0), + eventIds: new Float64Array(0), + tses: new BigInt64Array(0), utids: new Float64Array(0), trackKeys: [], sources: [], diff --git a/ui/src/frontend/search_handler.ts b/ui/src/frontend/search_handler.ts index d9e3f0df2..3fcc1783c 100644 --- a/ui/src/frontend/search_handler.ts +++ b/ui/src/frontend/search_handler.ts @@ -13,8 +13,10 @@ // limitations under the License. import {searchSegment} from '../base/binary_search'; +import {assertUnreachable} from '../base/logging'; import {Actions} from '../common/actions'; import {globals} from './globals'; +import {verticalScrollToTrack} from './scroll_helper'; function setToPrevious(current: number) { let index = current - 1; @@ -34,7 +36,7 @@ export function executeSearch(reverse = false) { const vizWindow = globals.stateVisibleTime(); const startNs = vizWindow.start; const endNs = vizWindow.end; - const currentTs = globals.currentSearchResults.tsStarts[index]; + const currentTs = globals.currentSearchResults.tses[index]; // If the value of |globals.currentSearchResults.totalResults| is 0, // it means that the query is in progress or no results are found. @@ -44,12 +46,12 @@ export function executeSearch(reverse = false) { // If this is a new search or the currentTs is not in the viewport, // select the first/last item in the viewport. - if (index === -1 || currentTs < startNs || currentTs > endNs) { + if ( + index === -1 || + (currentTs !== -1n && (currentTs < startNs || currentTs > endNs)) + ) { if (reverse) { - const [smaller] = searchSegment( - globals.currentSearchResults.tsStarts, - endNs, - ); + const [smaller] = searchSegment(globals.currentSearchResults.tses, endNs); // If there is no item in the viewport just go to the previous. if (smaller === -1) { setToPrevious(index); @@ -58,7 +60,7 @@ export function executeSearch(reverse = false) { } } else { const [, larger] = searchSegment( - globals.currentSearchResults.tsStarts, + globals.currentSearchResults.tses, startNs, ); // If there is no item in the viewport just go to the next. @@ -82,52 +84,61 @@ export function executeSearch(reverse = false) { function selectCurrentSearchResult() { const searchIndex = globals.state.searchIndex; const source = globals.currentSearchResults.sources[searchIndex]; - const currentId = globals.currentSearchResults.sliceIds[searchIndex]; + const currentId = globals.currentSearchResults.eventIds[searchIndex]; const trackKey = globals.currentSearchResults.trackKeys[searchIndex]; if (currentId === undefined) return; - if (source === 'cpu') { - globals.setLegacySelection( - { - kind: 'SLICE', - id: currentId, - trackKey, - }, - { - clearSearch: false, - pendingScrollId: currentId, - switchToCurrentSelectionTab: true, - }, - ); - } else if (source === 'log') { - globals.setLegacySelection( - { - kind: 'LOG', - id: currentId, - trackKey, - }, - { - clearSearch: false, - pendingScrollId: currentId, - switchToCurrentSelectionTab: true, - }, - ); - } else { - // Search results only include slices from the slice table for now. - // When we include annotations we need to pass the correct table. - globals.setLegacySelection( - { - kind: 'CHROME_SLICE', - id: currentId, - trackKey, - table: 'slice', - }, - { - clearSearch: false, - pendingScrollId: currentId, - switchToCurrentSelectionTab: true, - }, - ); + switch (source) { + case 'track': + verticalScrollToTrack(trackKey, true); + break; + case 'cpu': + globals.setLegacySelection( + { + kind: 'SLICE', + id: currentId, + trackKey, + }, + { + clearSearch: false, + pendingScrollId: currentId, + switchToCurrentSelectionTab: true, + }, + ); + break; + case 'log': + globals.setLegacySelection( + { + kind: 'LOG', + id: currentId, + trackKey, + }, + { + clearSearch: false, + pendingScrollId: currentId, + switchToCurrentSelectionTab: true, + }, + ); + break; + case 'slice': + // Search results only include slices from the slice table for now. + // When we include annotations we need to pass the correct table. + globals.setLegacySelection( + { + kind: 'CHROME_SLICE', + id: currentId, + trackKey, + table: 'slice', + }, + { + clearSearch: false, + pendingScrollId: currentId, + switchToCurrentSelectionTab: true, + }, + ); + break; + default: + assertUnreachable(source); } } diff --git a/ui/src/frontend/tickmark_panel.ts b/ui/src/frontend/tickmark_panel.ts index 270372089..90f3e4cbc 100644 --- a/ui/src/frontend/tickmark_panel.ts +++ b/ui/src/frontend/tickmark_panel.ts @@ -84,19 +84,21 @@ export class TickmarkPanel implements Panel { ); } const index = globals.state.searchIndex; - if (index !== -1 && index < globals.currentSearchResults.tsStarts.length) { - const start = globals.currentSearchResults.tsStarts[index]; - const triangleStart = - Math.max(visibleTimeScale.timeToPx(Time.fromRaw(start)), 0) + - TRACK_SHELL_WIDTH; - ctx.fillStyle = '#000'; - ctx.beginPath(); - ctx.moveTo(triangleStart, size.height); - ctx.lineTo(triangleStart - 3, 0); - ctx.lineTo(triangleStart + 3, 0); - ctx.lineTo(triangleStart, size.height); - ctx.fill(); - ctx.closePath(); + if (index !== -1 && index < globals.currentSearchResults.tses.length) { + const start = globals.currentSearchResults.tses[index]; + if (start !== -1n) { + const triangleStart = + Math.max(visibleTimeScale.timeToPx(Time.fromRaw(start)), 0) + + TRACK_SHELL_WIDTH; + ctx.fillStyle = '#000'; + ctx.beginPath(); + ctx.moveTo(triangleStart, size.height); + ctx.lineTo(triangleStart - 3, 0); + ctx.lineTo(triangleStart + 3, 0); + ctx.lineTo(triangleStart, size.height); + ctx.fill(); + ctx.closePath(); + } } ctx.restore(); |