1// Copyright (C) 2018 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 {RawQueryResult, TraceProcessor} from './protos'; 16import {TimeSpan} from './time'; 17 18/** 19 * Abstract interface of a trace proccessor. 20 * This class is wrapper for multiple proto services defined in: 21 * //protos/perfetto/trace_processor/* 22 * For each service ("FooService") Engine will have abstract getter 23 * ("fooService") which returns a protobufjs rpc.Service object for 24 * the given service. 25 * 26 * Engine also defines helpers for the most common service methods 27 * (e.g. query). 28 */ 29export abstract class Engine { 30 abstract readonly id: string; 31 private _numCpus?: number; 32 33 /** 34 * Push trace data into the engine. The engine is supposed to automatically 35 * figure out the type of the trace (JSON vs Protobuf). 36 */ 37 abstract parse(data: Uint8Array): void; 38 39 /** 40 * Notify the engine no more data is coming. 41 */ 42 abstract notifyEof(): void; 43 44 /* 45 * The RCP interface to call service methods defined in trace_processor.proto. 46 */ 47 abstract get rpc(): TraceProcessor; 48 49 /** 50 * Shorthand for sending a SQL query to the engine. 51 * Exactly the same as engine.rpc.rawQuery({rawQuery}); 52 */ 53 query(sqlQuery: string): Promise<RawQueryResult> { 54 const timeQueuedNs = Math.floor(performance.now() * 1e6); 55 return this.rpc.rawQuery({sqlQuery, timeQueuedNs}); 56 } 57 58 async queryOneRow(query: string): Promise<number[]> { 59 const result = await this.query(query); 60 const res: number[] = []; 61 result.columns.map(c => res.push(+c.longValues![0])); 62 return res; 63 } 64 65 // TODO(hjd): When streaming must invalidate this somehow. 66 async getNumberOfCpus(): Promise<number> { 67 if (!this._numCpus) { 68 const result = await this.query( 69 'select count(distinct(cpu)) as cpuCount from sched;'); 70 this._numCpus = +result.columns[0].longValues![0]; 71 } 72 return this._numCpus; 73 } 74 75 // TODO: This should live in code that's more specific to chrome, instead of 76 // in engine. 77 async getNumberOfProcesses(): Promise<number> { 78 const result = await this.query('select count(*) from process;'); 79 return +result.columns[0].longValues![0]; 80 } 81 82 async getTraceTimeBounds(): Promise<TimeSpan> { 83 const query = `select start_ts, end_ts from trace_bounds`; 84 const res = (await this.queryOneRow(query)); 85 return new TimeSpan(res[0] / 1e9, res[1] / 1e9); 86 } 87} 88