blob: 3e0399ff60d8c684ae4490781b8942526466840f [file] [log] [blame]
/**
* @license
* Copyright 2017 The Bazel Authors. All rights reserved.
*
* 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.
*/
/**
* perf_trace records traces in the Chrome Trace format (which is actually used
* for more than just Chrome). See:
* https://github.com/catapult-project/catapult/blob/master/tracing/README.md
*/
import * as fs from 'fs';
type Microseconds = number;
/** @return a high-res timestamp of the current time. */
function now(): Microseconds {
const [sec, nsec] = process.hrtime();
return (sec * 1e6) + (nsec / 1e3);
}
/**
* The type of entries in the Chrome Trace format:
* https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit
* Field names are chosen to match the JSON format.
*/
declare interface Event {
name: string;
ph: 'B'|'E'|'X'|'C';
pid: number; // Required field in the trace viewer, but we don't use it.
ts: Microseconds;
dur?: Microseconds;
args?: any;
}
const events: Event[] = [];
/** wrap wraps enter()/leave() calls around a block of code. */
export function wrap<T>(name: string, f: () => T): T {
const start = now();
try {
return f();
} finally {
const end = now();
events.push({name, ph: 'X', pid: 1, ts: start, dur: (end - start)});
}
}
/**
* counter records a snapshot of counts. The counter name identifies a
* single graph, while the counts object provides data for each count
* of a line on the stacked bar graph.
*/
export function counter(name: string, counts: {[name: string]: number}) {
events.push({name, ph: 'C', pid: 1, ts: now(), args: counts});
}
/** write writes the trace in Chrome Trace format to a given path. */
export function write(path: string) {
fs.writeFileSync(path, JSON.stringify(events), {encoding: 'utf8'});
}
/** Record the current heap usage to the performance trace. */
export function snapshotMemoryUsage() {
const snapshot = process.memoryUsage();
// The counter displays as a stacked bar graph, so compute metrics
// that sum to the appropriate total.
const unused = snapshot.heapTotal - snapshot.heapUsed;
counter('memory', {'used': snapshot.heapUsed, 'unused': unused});
}