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 {colorForState} from '../../components/colorizer'; 16import {LONG, NUM, NUM_NULL, STR} from '../../trace_processor/query_result'; 17import {translateState} from '../../components/sql_utils/thread_state'; 18import {ThreadStateDetailsPanel} from './thread_state_details_panel'; 19import {Trace} from '../../public/trace'; 20import {SourceDataset} from '../../trace_processor/dataset'; 21import {DatasetSliceTrack} from '../../components/tracks/dataset_slice_track'; 22 23export function createThreadStateTrack( 24 trace: Trace, 25 uri: string, 26 utid: number, 27) { 28 return new DatasetSliceTrack({ 29 trace, 30 uri, 31 dataset: new SourceDataset({ 32 schema: { 33 id: NUM, 34 ts: LONG, 35 dur: LONG, 36 cpu: NUM_NULL, 37 state: STR, 38 io_wait: NUM_NULL, 39 utid: NUM, 40 }, 41 src: 'thread_state', 42 filter: { 43 col: 'utid', 44 eq: utid, 45 }, 46 }), 47 // Make thread slice tracks a little shorter in height. 48 sliceLayout: { 49 sliceHeight: 12, 50 titleSizePx: 10, 51 }, 52 queryGenerator: (dataset) => { 53 // We actually abuse the depth provider here just a little. Instead of 54 // providing just a depth value, we also filter out non-sleeping/idle 55 // slices. In effect, we're using this function as a little escape hatch 56 // to override the query that's used for track rendering. 57 // 58 // The reason we don't just filter out sleeping/idle slices in the main 59 // dataset is because we don't want to filter the dataset exposed via 60 // getDataset(), we only want to filter them out at the rendering stage. 61 // 62 // The reason we don't want to render these slices is slightly nuanced. 63 // Essentially, if we render all slices and zoom out, the vast majority of 64 // the track is covered by sleeping slices, and the important 65 // runnable/running/etc slices are no longer rendered (effectively 66 // sleeping slices always 'win' on every bucket) so we lost the important 67 // detail. We could get around this if we had some way to tell the 68 // algorithm to prioritize some slices over others. 69 return ` 70 select 71 0 as depth, 72 * 73 from (${dataset.query()}) 74 where state not in ('S', 'I') 75 `; 76 }, 77 colorizer: (row) => { 78 const title = getState(row); 79 return colorForState(title); 80 }, 81 sliceName: (row) => { 82 return getState(row); 83 }, 84 detailsPanel: (row) => new ThreadStateDetailsPanel(trace, row.id), 85 rootTableName: 'thread_state', 86 }); 87} 88 89function getState(row: {io_wait: number | null; state: string}) { 90 const ioWait = row.io_wait === null ? undefined : Boolean(row.io_wait); 91 return translateState(row.state, ioWait); 92} 93