aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLalit Maganti <lalitm@google.com>2024-04-26 15:28:20 +0100
committerLalit Maganti <lalitm@google.com>2024-04-26 15:28:20 +0100
commit6e0ff97cfca7698faf1b029b1cf2082540087516 (patch)
treeb28a75d31961e55d0b5dce59ad525206bb43372e
parent34582f5b87c886a55341f09544c43441da4b6f0a (diff)
downloadperfetto-6e0ff97cfca7698faf1b029b1cf2082540087516.tar.gz
ui: add tracks to list of searchable items
Change-Id: I128a0a04fb8714f51caa09ef8b749f5c74baae72
-rw-r--r--ui/src/common/search_data.ts8
-rw-r--r--ui/src/controller/search_controller.ts143
-rw-r--r--ui/src/frontend/globals.ts8
-rw-r--r--ui/src/frontend/search_handler.ts111
-rw-r--r--ui/src/frontend/tickmark_panel.ts28
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();