blob: bd47f4fd4c80873edecd7108a9bd86ef9fa6c1c0 [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 {RawQueryResult, TraceProcessor} from './protos';
import {TimeSpan} from './time';
/**
* Abstract interface of a trace proccessor.
* This class is wrapper for multiple proto services defined in:
* //protos/perfetto/trace_processor/*
* For each service ("FooService") Engine will have abstract getter
* ("fooService") which returns a protobufjs rpc.Service object for
* the given service.
*
* Engine also defines helpers for the most common service methods
* (e.g. query).
*/
export abstract class Engine {
abstract readonly id: string;
/**
* Push trace data into the engine. The engine is supposed to automatically
* figure out the type of the trace (JSON vs Protobuf).
*/
abstract parse(data: Uint8Array): void;
/**
* Notify the engine no more data is coming.
*/
abstract notifyEof(): void;
/*
* The RCP interface to call service methods defined in trace_processor.proto.
*/
abstract get rpc(): TraceProcessor;
/**
* Shorthand for sending a SQL query to the engine.
* Exactly the same as engine.rpc.rawQuery({rawQuery});
*/
query(sqlQuery: string): Promise<RawQueryResult> {
const timeQueuedNs = Math.floor(performance.now() * 1e6);
return this.rpc.rawQuery({sqlQuery, timeQueuedNs});
}
async queryOneRow(query: string): Promise<number[]> {
const result = await this.query(query);
const res: number[] = [];
result.columns.map(c => res.push(+c.longValues![0]));
return res;
}
// TODO(hjd): Maybe we should cache result? But then Engine must be
// streaming aware.
async getNumberOfCpus(): Promise<number> {
const result =
await this.query('select count(distinct(cpu)) as cpuCount from sched;');
return +result.columns[0].longValues![0];
}
// TODO: This should live in code that's more specific to chrome, instead of
// in engine.
async getNumberOfProcesses(): Promise<number> {
const result = await this.query('select count(*) from process;');
return +result.columns[0].longValues![0];
}
async getTraceTimeBounds(): Promise<TimeSpan> {
const maxQuery = `select max(ts) from (
select max(ts) as ts from sched
union all select max(ts) as ts from slices
union all select max(ts) as ts from counters
)`;
const minQuery = `select min(ts) from (
select min(ts) as ts from sched
union all select min(ts) as ts from slices
union all select min(ts) as ts from counters
)`;
const start = (await this.queryOneRow(minQuery))[0];
const end = (await this.queryOneRow(maxQuery))[0];
return new TimeSpan(start / 1e9, end / 1e9);
}
}