blob: 186491a5f75151de30d997c75c16b960b295cfb7 [file] [log] [blame]
// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import {fromNs} from '../../common/time';
import {
TrackController,
trackControllerRegistry
} from '../../controller/track_controller';
import {Config, Data, SLICE_TRACK_KIND} from './common';
class ChromeSliceTrackController extends TrackController<Config, Data> {
static readonly kind = SLICE_TRACK_KIND;
private busy = false;
onBoundsChange(start: number, end: number, resolution: number) {
// TODO: we should really call TraceProcessor.Interrupt() at this point.
if (this.busy) return;
const LIMIT = 10000;
// TODO: "ts >= x - dur" below is inefficient because doesn't allow to use
// any index. We need to introduce ts_lower_bound also for the slices table
// (see sched table).
const query = `select ts,dur,depth,cat,name from slices ` +
`where utid = ${this.config.utid} ` +
`and ts >= ${Math.round(start * 1e9)} - dur ` +
`and ts <= ${Math.round(end * 1e9)} ` +
`and dur >= ${Math.round(resolution * 1e9)} ` +
`order by ts ` +
`limit ${LIMIT};`;
this.busy = true;
this.engine.query(query).then(rawResult => {
this.busy = false;
if (rawResult.error) {
throw new Error(`Query error "${query}": ${rawResult.error}`);
}
const numRows = +rawResult.numRecords;
const slices: Data = {
start,
end,
resolution,
strings: [],
starts: new Float64Array(numRows),
ends: new Float64Array(numRows),
depths: new Uint16Array(numRows),
titles: new Uint16Array(numRows),
categories: new Uint16Array(numRows),
};
const stringIndexes = new Map<string, number>();
function internString(str: string) {
let idx = stringIndexes.get(str);
if (idx !== undefined) return idx;
idx = slices.strings.length;
slices.strings.push(str);
stringIndexes.set(str, idx);
return idx;
}
for (let row = 0; row < numRows; row++) {
const cols = rawResult.columns;
const startSec = fromNs(+cols[0].longValues![row]);
slices.starts[row] = startSec;
slices.ends[row] = startSec + fromNs(+cols[1].longValues![row]);
slices.depths[row] = +cols[2].longValues![row];
slices.categories[row] = internString(cols[3].stringValues![row]);
slices.titles[row] = internString(cols[4].stringValues![row]);
}
if (numRows === LIMIT) {
slices.end = slices.ends[slices.ends.length - 1];
}
this.publish(slices);
});
}
}
trackControllerRegistry.register(ChromeSliceTrackController);