• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2023 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15import {BigintMath as BIMath} from '../../base/bigint_math';
16import {clamp} from '../../base/math_utils';
17import {ThreadSliceDetailsPanel} from '../../components/details/thread_slice_details_tab';
18import {DatasetSliceTrack} from '../../components/tracks/dataset_slice_track';
19import {TrackEventDetailsPanel} from '../../public/details_panel';
20import {Trace} from '../../public/trace';
21import {SourceDataset} from '../../trace_processor/dataset';
22import {
23  LONG,
24  LONG_NULL,
25  NUM,
26  STR_NULL,
27} from '../../trace_processor/query_result';
28
29export interface TraceProcessorSliceTrackAttrs {
30  readonly trace: Trace;
31  readonly uri: string;
32  readonly maxDepth?: number;
33  readonly trackIds: ReadonlyArray<number>;
34  readonly detailsPanel?: (row: {id: number}) => TrackEventDetailsPanel;
35}
36
37export function createTraceProcessorSliceTrack({
38  trace,
39  uri,
40  maxDepth,
41  trackIds,
42  detailsPanel,
43}: TraceProcessorSliceTrackAttrs) {
44  return new DatasetSliceTrack({
45    trace,
46    uri,
47    dataset: new SourceDataset({
48      schema: {
49        id: NUM,
50        ts: LONG,
51        dur: LONG,
52        name: STR_NULL,
53        depth: NUM,
54        thread_dur: LONG_NULL,
55      },
56      src: 'slice',
57      filter: {
58        col: 'track_id',
59        in: trackIds,
60      },
61    }),
62    sliceName: (row) => (row.name === null ? '[null]' : row.name),
63    initialMaxDepth: maxDepth,
64    rootTableName: 'slice',
65    queryGenerator: getDepthProvider(trackIds),
66    fillRatio: (row) => {
67      if (row.dur > 0n && row.thread_dur !== null) {
68        return clamp(BIMath.ratio(row.thread_dur, row.dur), 0, 1);
69      } else {
70        return 1;
71      }
72    },
73    detailsPanel: detailsPanel
74      ? (row) => detailsPanel(row)
75      : () => new ThreadSliceDetailsPanel(trace),
76  });
77}
78
79function getDepthProvider(trackIds: ReadonlyArray<number>) {
80  // If we have more than one track we basically just need to replace the query
81  // used for rendering tracks with this one which uses
82  // experimental_slice_layout. The reason we don't just put this query in the
83  // dataset is that the dataset is shared with the outside world and we don't
84  // want to force everyone else to use experimental_slice_track.
85  // TODO(stevegolton): Let's teach internal_layout how to mimic this behaviour.
86  if (trackIds.length > 1) {
87    return () => `
88      select
89        id,
90        ts,
91        dur,
92        layout_depth as depth,
93        name,
94        thread_dur
95      from experimental_slice_layout
96      where filter_track_ids = '${trackIds.join(',')}'
97    `;
98  } else {
99    return undefined;
100  }
101}
102