mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
Wrap performance metrics in object to reduce deoptimizations on ts namespace.
This commit is contained in:
parent
60e1ae0e9f
commit
b8a9efb66c
@ -3,8 +3,6 @@
|
||||
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
export let bindTime = 0;
|
||||
|
||||
export const enum ModuleInstanceState {
|
||||
NonInstantiated = 0,
|
||||
Instantiated = 1,
|
||||
@ -96,9 +94,10 @@ namespace ts {
|
||||
const binder = createBinder();
|
||||
|
||||
export function bindSourceFile(file: SourceFile, options: CompilerOptions) {
|
||||
const start = new Date().getTime();
|
||||
Performance.mark("bindStart");
|
||||
binder(file, options);
|
||||
bindTime += new Date().getTime() - start;
|
||||
Performance.mark("bindEnd");
|
||||
Performance.measure("bindTime", "bindStart", "bindEnd");
|
||||
}
|
||||
|
||||
function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
|
||||
|
||||
@ -14,8 +14,6 @@ namespace ts {
|
||||
return node.id;
|
||||
}
|
||||
|
||||
export let checkTime = 0;
|
||||
|
||||
export function getSymbolId(symbol: Symbol): number {
|
||||
if (!symbol.id) {
|
||||
symbol.id = nextSymbolId;
|
||||
@ -16066,11 +16064,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
function checkSourceFile(node: SourceFile) {
|
||||
const start = new Date().getTime();
|
||||
Performance.mark("checkStart");
|
||||
|
||||
checkSourceFileWorker(node);
|
||||
|
||||
checkTime += new Date().getTime() - start;
|
||||
Performance.mark("checkEnd");
|
||||
Performance.measure("checkTime", "checkStart", "checkEnd");
|
||||
}
|
||||
|
||||
// Fully type check a source file and collect the relevant diagnostics.
|
||||
|
||||
@ -1134,4 +1134,139 @@ namespace ts {
|
||||
: ((fileName) => fileName.toLowerCase());
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export namespace Performance {
|
||||
interface MarkData {
|
||||
markName: string;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
interface MeasureData {
|
||||
measureName: string;
|
||||
startMarkName: string;
|
||||
endMarkName: string;
|
||||
timestamp: number;
|
||||
marksOffset: number;
|
||||
}
|
||||
|
||||
export interface Measure {
|
||||
name: string;
|
||||
startTime: number;
|
||||
duration: number;
|
||||
}
|
||||
|
||||
const marks: MarkData[] = [];
|
||||
const measures: MeasureData[] = [];
|
||||
|
||||
let start = now();
|
||||
|
||||
/** Gets the current timer for performance measurements. */
|
||||
export function now() {
|
||||
// TODO(rbuckton): Determine if there is a higher-resolution timer we can use.
|
||||
return Date.now();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a performance mark with the specified name.
|
||||
*
|
||||
* @param markName The name of the performance mark.
|
||||
*/
|
||||
export function mark(markName: string) {
|
||||
marks.push({ markName, timestamp: now() });
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a performance measurement with the specified name.
|
||||
*
|
||||
* @param measureName The name of the performance measurement.
|
||||
* @param startMarkName The name of the starting mark.
|
||||
* If provided, the most recent time value of the start mark is used.
|
||||
* If not specified, the value is the time that the performance service was
|
||||
* initialized or the last time it was reset.
|
||||
* @param endMarkName The name of the ending mark.
|
||||
* If provided, the most recent time value of the end mark is used.
|
||||
* If not specified, the current time is used.
|
||||
*/
|
||||
export function measure(measureName: string, startMarkName?: string, endMarkName?: string) {
|
||||
measures.push({
|
||||
measureName,
|
||||
startMarkName,
|
||||
endMarkName,
|
||||
timestamp: now(),
|
||||
marksOffset: marks.length
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of performance measures.
|
||||
*
|
||||
* @param measureName The name of the measure.
|
||||
* If provided, only measures with the provided name are returned.
|
||||
* If not specified, all measures are returned since the last time the
|
||||
* performance service was reset.
|
||||
*/
|
||||
export function getMeasures(measureName?: string) {
|
||||
const result: Measure[] = [];
|
||||
for (const measure of measures) {
|
||||
if (measureName !== undefined && measureName !== measure.measureName) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let startOffset = 0;
|
||||
let startTime = start;
|
||||
if (measure.startMarkName) {
|
||||
const startMarkIndex = getMarkOffset(measure.startMarkName, 0, measure.marksOffset);
|
||||
if (startMarkIndex >= 0) {
|
||||
startOffset = startMarkIndex;
|
||||
startTime = marks[startMarkIndex].timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
let endTime = measure.timestamp;
|
||||
if (measure.endMarkName) {
|
||||
const endMarkIndex = getMarkOffset(measure.endMarkName, startOffset, measure.marksOffset);
|
||||
if (endMarkIndex >= 0) {
|
||||
endTime = marks[endMarkIndex].timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
const duration = endTime - startTime;
|
||||
result.push({
|
||||
name: measure.measureName,
|
||||
startTime,
|
||||
duration
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function getMarkOffset(markName: string, markStart: number, markEnd: number) {
|
||||
if (markName === undefined) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (markStart < 0) {
|
||||
markStart = 0;
|
||||
}
|
||||
|
||||
for (let i = markEnd - 1; i >= markStart; i--) {
|
||||
const mark = marks[i];
|
||||
if (mark.markName === markName) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all marks and measurements in the performance service.
|
||||
*/
|
||||
export function reset() {
|
||||
marks.length = 0;
|
||||
measures.length = 0;
|
||||
start = now();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,11 +4,6 @@
|
||||
/// <reference path="printer.ts" />
|
||||
|
||||
namespace ts {
|
||||
/* @internal */ export let programTime = 0;
|
||||
/* @internal */ export let emitTime = 0;
|
||||
/* @internal */ export let ioReadTime = 0;
|
||||
/* @internal */ export let ioWriteTime = 0;
|
||||
|
||||
/** The version of the TypeScript compiler release */
|
||||
|
||||
const emptyArray: any[] = [];
|
||||
@ -781,9 +776,10 @@ namespace ts {
|
||||
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile {
|
||||
let text: string;
|
||||
try {
|
||||
const start = new Date().getTime();
|
||||
Performance.mark("ioReadStart");
|
||||
text = sys.readFile(fileName, options.charset);
|
||||
ioReadTime += new Date().getTime() - start;
|
||||
Performance.mark("ioReadEnd");
|
||||
Performance.measure("ioReadTime", "ioReadStart", "ioReadEnd");
|
||||
}
|
||||
catch (e) {
|
||||
if (onError) {
|
||||
@ -850,7 +846,7 @@ namespace ts {
|
||||
|
||||
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
|
||||
try {
|
||||
const start = new Date().getTime();
|
||||
Performance.mark("ioWriteStart");
|
||||
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
|
||||
|
||||
if (isWatchSet(options) && sys.createHash && sys.getModifiedTime) {
|
||||
@ -860,7 +856,8 @@ namespace ts {
|
||||
sys.writeFile(fileName, data, writeByteOrderMark);
|
||||
}
|
||||
|
||||
ioWriteTime += new Date().getTime() - start;
|
||||
Performance.mark("ioWriteEnd");
|
||||
Performance.measure("ioWriteTime", "ioWriteStart", "ioWriteEnd");
|
||||
}
|
||||
catch (e) {
|
||||
if (onError) {
|
||||
@ -962,7 +959,7 @@ namespace ts {
|
||||
let resolvedTypeReferenceDirectives: Map<ResolvedTypeReferenceDirective> = {};
|
||||
let fileProcessingDiagnostics = createDiagnosticCollection();
|
||||
|
||||
const start = new Date().getTime();
|
||||
Performance.mark("programStart");
|
||||
|
||||
host = host || createCompilerHost(options);
|
||||
|
||||
@ -1055,7 +1052,8 @@ namespace ts {
|
||||
|
||||
verifyCompilerOptions();
|
||||
|
||||
programTime += new Date().getTime() - start;
|
||||
Performance.mark("programEnd");
|
||||
Performance.measure("programTime", "programStart", "programEnd");
|
||||
|
||||
return program;
|
||||
|
||||
@ -1288,7 +1286,7 @@ namespace ts {
|
||||
// checked is to not pass the file to getEmitResolver.
|
||||
const emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver((options.outFile || options.out) ? undefined : sourceFile);
|
||||
|
||||
const start = new Date().getTime();
|
||||
Performance.mark("emitStart");
|
||||
|
||||
// TODO(rbuckton): remove USE_TRANSFORMS condition when we switch to transforms permanently.
|
||||
let useLegacyEmitter = options.useLegacyEmitter;
|
||||
@ -1302,7 +1300,9 @@ namespace ts {
|
||||
getEmitHost(writeFileCallback),
|
||||
sourceFile);
|
||||
|
||||
emitTime += new Date().getTime() - start;
|
||||
Performance.mark("emitEnd");
|
||||
Performance.measure("emitTime", "emitStart", "emitEnd");
|
||||
|
||||
return emitResult;
|
||||
}
|
||||
|
||||
@ -2076,7 +2076,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Cannot specify module gen that isn't amd or system with --out
|
||||
// Report this error if user specified --module moduleKind
|
||||
// Report this error if user specified --module moduleKind
|
||||
// or if there is external module in compilation which defaults to commonjs
|
||||
const emitModuleKind = getEmitModuleKind(options);
|
||||
if (outFile && (options.module || firstExternalModuleSourceFile) && !(emitModuleKind === ModuleKind.AMD || emitModuleKind === ModuleKind.System)) {
|
||||
|
||||
@ -544,12 +544,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function compile(fileNames: string[], compilerOptions: CompilerOptions, compilerHost: CompilerHost) {
|
||||
ioReadTime = 0;
|
||||
ioWriteTime = 0;
|
||||
programTime = 0;
|
||||
bindTime = 0;
|
||||
checkTime = 0;
|
||||
emitTime = 0;
|
||||
Performance.reset();
|
||||
|
||||
const program = createProgram(fileNames, compilerOptions, compilerHost);
|
||||
const exitStatus = compileProgram();
|
||||
@ -561,6 +556,13 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (compilerOptions.diagnostics) {
|
||||
const ioReadTime = reduceLeft(Performance.getMeasures("ioReadTime"), (aggregate, measure) => aggregate + measure.duration, 0);
|
||||
const ioWriteTime = reduceLeft(Performance.getMeasures("ioWriteTime"), (aggregate, measure) => aggregate + measure.duration, 0);
|
||||
const programTime = reduceLeft(Performance.getMeasures("programTime"), (aggregate, measure) => aggregate + measure.duration, 0);
|
||||
const bindTime = reduceLeft(Performance.getMeasures("bindTime"), (aggregate, measure) => aggregate + measure.duration, 0);
|
||||
const checkTime = reduceLeft(Performance.getMeasures("checkTime"), (aggregate, measure) => aggregate + measure.duration, 0);
|
||||
const emitTime = reduceLeft(Performance.getMeasures("emitTime"), (aggregate, measure) => aggregate + measure.duration, 0);
|
||||
|
||||
const memoryUsed = sys.getMemoryUsage ? sys.getMemoryUsage() : -1;
|
||||
reportCountStatistic("Files", program.getSourceFiles().length);
|
||||
reportCountStatistic("Lines", countLines(program));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user