aboutsummaryrefslogtreecommitdiff
path: root/ui/src/common/engine.ts
blob: 0ec3be35084dd00478a664804b952604f2ae317f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// 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;
  private _numCpus?: number;

  /**
   * 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): When streaming must invalidate this somehow.
  async getNumberOfCpus(): Promise<number> {
    if (!this._numCpus) {
      const result = await this.query(
          'select count(distinct(cpu)) as cpuCount from sched;');
      this._numCpus = +result.columns[0].longValues![0];
    }
    return this._numCpus;
  }

  // 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 query = `select start_ts, end_ts from trace_bounds`;
    const res = (await this.queryOneRow(query));
    return new TimeSpan(res[0] / 1e9, res[1] / 1e9);
  }
}