Skip to content

Commit

Permalink
Merged in bdo/tracing (pull request #86)
Browse files Browse the repository at this point in the history
Add tracing measurements to phases in Parcel

Approved-by: Niklas Mischkulnig
Approved-by: Marcin Szczepanski
  • Loading branch information
thebriando committed Jul 27, 2022
2 parents f2b96b2 + 39aeffa commit 49f8205
Show file tree
Hide file tree
Showing 10 changed files with 170 additions and 6 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ tmp
parcel-bundle-reports/
.verdaccio_storage/
sourcemap-info.json
parcel-trace.json
3 changes: 2 additions & 1 deletion flow-libs/chrome-trace-event.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ declare module 'chrome-trace-event' {
parent?: Tracer | null,
fields?: Fields | null,
objectMode?: boolean | null,
noStream?: boolean
noStream?: boolean,
|};

declare type Fields = {
Expand All @@ -18,6 +18,7 @@ declare module 'chrome-trace-event' {
declare export class Tracer extends stream$Readable {
constructor(opts?: TracerOptions): Tracer;
begin(fields: Fields): void;
end(fields: Fields): void;
completeEvent(fields: Fields): void;
instantEvent(fields: Fields): void;
flush(): void;
Expand Down
11 changes: 9 additions & 2 deletions packages/core/core/src/Parcel.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import WorkerFarm from '@parcel/workers';
import nullthrows from 'nullthrows';
import {BuildAbortError} from './utils';
import {loadParcelConfig} from './requests/ParcelConfigRequest';
import ReporterRunner from './ReporterRunner';
import ReporterRunner, {report} from './ReporterRunner';
import dumpGraphToGraphViz from './dumpGraphToGraphViz';
import resolveOptions from './resolveOptions';
import {ValueEmitter} from '@parcel/events';
Expand All @@ -31,6 +31,7 @@ import {AbortController} from 'abortcontroller-polyfill/dist/cjs-ponyfill';
import {PromiseQueue} from '@parcel/utils';
import ParcelConfig from './ParcelConfig';
import logger from '@parcel/logger';
import Tracer from './Tracer';
import RequestTracker, {
getWatcherOptions,
requestGraphEdgeTypes,
Expand All @@ -56,6 +57,7 @@ export default class Parcel {
#initialOptions /*: InitialParcelOptions*/;
#reporterRunner /*: ReporterRunner*/;
#resolvedOptions /*: ?ParcelOptions*/ = null;
#tracer /*: Tracer */;
#optionsRef /*: SharedReference */;
#watchAbortController /*: AbortController*/;
#watchQueue /*: PromiseQueue<?BuildEvent>*/ = new PromiseQueue<?BuildEvent>({
Expand Down Expand Up @@ -108,6 +110,7 @@ export default class Parcel {
}

await resolvedOptions.cache.ensure();
this.#tracer = new Tracer(report);

let {dispose: disposeOptions, ref: optionsRef} =
await this.#farm.createSharedReference(resolvedOptions);
Expand Down Expand Up @@ -268,7 +271,11 @@ export default class Parcel {
});

let {bundleGraph, bundleInfo, changedAssets, assetRequests} =
await this.#requestTracker.runRequest(request, {force: true});
await this.#requestTracker.runRequest(
request,
{force: true},
this.#tracer,
);

this.#requestedAssetIds.clear();

Expand Down
4 changes: 4 additions & 0 deletions packages/core/core/src/RequestTracker.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import {
STARTUP,
ERROR,
} from './constants';
import Tracer from './Tracer';

export const requestGraphEdgeTypes = {
subrequest: 2,
Expand Down Expand Up @@ -158,6 +159,7 @@ export type StaticRunOpts = {|
options: ParcelOptions,
api: RunAPI,
invalidateReason: InvalidateReason,
tracer?: Tracer,
|};

const nodeFromFilePath = (filePath: ProjectPath): RequestGraphNode => ({
Expand Down Expand Up @@ -905,6 +907,7 @@ export default class RequestTracker {
async runRequest<TInput, TResult>(
request: Request<TInput, TResult>,
opts?: ?RunRequestOpts,
tracer?: Tracer,
): Async<TResult> {
let requestId = this.graph.hasContentKey(request.id)
? this.graph.getNodeIdByContentKey(request.id)
Expand Down Expand Up @@ -952,6 +955,7 @@ export default class RequestTracker {
farm: this.farm,
options: this.options,
invalidateReason: node.invalidateReason,
tracer,
});

assertSignalNotAborted(this.signal);
Expand Down
50 changes: 50 additions & 0 deletions packages/core/core/src/Tracer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// @flow strict-local

import type {Tracer as ITracer, Measurement} from '@parcel/types';
import type {ReportFn} from './types';

// $FlowFixMe
import {performance as _performance} from 'perf_hooks';

let tid;
try {
tid = require('worker_threads').threadId;
} catch {
tid = 0;
}

const performance: Performance = _performance;
const pid = process.pid;

export default class Tracer implements ITracer {
_report /*: ReportFn */;

constructor(report: ReportFn) {
this._report = report;
}

async wrap(name: string, fn: () => mixed): Promise<void> {
let measurement = this.createMeasurement(name);
try {
await fn();
} finally {
measurement.end();
}
}

createMeasurement(name: string): Measurement {
const start = performance.now();
return {
end: () => {
this._report({
name,
pid,
tid,
duration: performance.now() - start,
ts: start,
type: 'trace',
});
},
};
}
}
21 changes: 20 additions & 1 deletion packages/core/core/src/requests/ParcelBuildRequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,15 @@ export default function createParcelBuildRequest(
};
}

async function run({input, api, options}: RunInput) {
async function run({input, api, options, tracer}: RunInput) {
let {optionsRef, requestedAssetIds, signal} = input;
let transformationMeasurement;
let bundlingMeasurement;
let packagingRequest;

if (tracer) {
transformationMeasurement = tracer.createMeasurement('transformation');
}
let request = createAssetGraphRequest({
name: 'Main',
entries: options.entries,
Expand All @@ -66,6 +73,11 @@ async function run({input, api, options}: RunInput) {
force: options.shouldBuildLazily && requestedAssetIds.size > 0,
});

transformationMeasurement && transformationMeasurement.end();

if (tracer) {
bundlingMeasurement = tracer.createMeasurement('bundling');
}
let bundleGraphRequest = createBundleGraphRequest({
assetGraph,
previousAssetGraphHash,
Expand All @@ -76,19 +88,26 @@ async function run({input, api, options}: RunInput) {
let {bundleGraph, changedAssets: changedRuntimeAssets} = await api.runRequest(
bundleGraphRequest,
);

bundlingMeasurement && bundlingMeasurement.end();

for (let [id, asset] of changedRuntimeAssets) {
changedAssets.set(id, asset);
}

// $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 (Windows only)
dumpGraphToGraphViz(bundleGraph._graph, 'BundleGraph', bundleGraphEdgeTypes);

if (tracer) {
packagingRequest = tracer.createMeasurement('packaging');
}
let writeBundlesRequest = createWriteBundlesRequest({
bundleGraph,
optionsRef,
});

let bundleInfo = await api.runRequest(writeBundlesRequest);
packagingRequest && packagingRequest.end();
assertSignalNotAborted(signal);

return {bundleGraph, bundleInfo, changedAssets, assetRequests};
Expand Down
18 changes: 18 additions & 0 deletions packages/core/types/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1823,6 +1823,7 @@ export type ReporterEvent =
| BuildProgressEvent
| BuildSuccessEvent
| BuildFailureEvent
| TraceEvent
| WatchStartEvent
| WatchEndEvent
| ValidationEvent;
Expand All @@ -1849,3 +1850,20 @@ export interface IDisposable {
export type AsyncSubscription = {|
unsubscribe(): Promise<mixed>,
|};

// Loosely modeled on Chrome's Trace Event format:
// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview
export type TraceEvent = {|
+type: 'trace',
+ts: number,
+duration: number,
+name: string,
+tid: number,
+pid: number,
|};

export type Measurement = {|end: () => void|};

export interface Tracer {
createMeasurement(name: string): Measurement;
}
27 changes: 27 additions & 0 deletions packages/reporters/trace/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "@parcel/reporter-trace",
"version": "2.0.35",
"license": "MIT",
"publishConfig": {
"access": "public"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
},
"repository": {
"type": "git",
"url": "https://github.com/parcel-bundler/parcel.git"
},
"main": "lib/TraceReporter.js",
"source": "src/TraceReporter.js",
"engines": {
"node": ">= 10.0.0",
"parcel": "2.0.35"
},
"dependencies": {
"@parcel/plugin": "2.0.35",
"@parcel/utils": "2.0.35",
"chrome-trace-event": "^1.0.2"
}
}
35 changes: 35 additions & 0 deletions packages/reporters/trace/src/TraceReporter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// @flow strict-local

import {Reporter} from '@parcel/plugin';
import fs from 'fs';
import {Tracer} from 'chrome-trace-event';

const tracer = new Tracer();
tracer.pipe(fs.createWriteStream('parcel-trace.json'));

export default (new Reporter({
report({event}) {
switch (event.type) {
case 'trace': {
tracer.completeEvent({
name: event.name,
ts: millisecondsToMicroseconds(event.ts),
dur: millisecondsToMicroseconds(event.duration),
tid: event.tid,
pid: event.pid,
});
break;
}
case 'buildSuccess':
tracer.push(']');
break;
case 'buildFailure':
tracer.flush();
break;
}
},
}): Reporter);

function millisecondsToMicroseconds(milliseconds: number) {
return Math.floor(milliseconds * 1000);
}
6 changes: 4 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2556,6 +2556,7 @@
detect-libc "^1.0.3"

"@parcel/[email protected]+a9193ce0b", "self-published@npm:@parcel/[email protected]":
name self-published
version "2.6.3-nightly.2759"
resolved "https://packages.atlassian.com/api/npm/npm-remote/@parcel/fs-search/-/fs-search-2.6.3-nightly.2759.tgz#aeeedcd5809c054bf793e3f8585d1068ac6bd650"
integrity sha512-g+imNZhWyzIjnd8079+6QFwgWRvqdJlJyensIFM2vn509+gm3uWFuM330EQVucLcy8O8VkB/Kd3tOD+GntsUtQ==
Expand Down Expand Up @@ -2601,6 +2602,7 @@
xxhash-wasm "^0.4.2"

"@parcel/[email protected]+a9193ce0b", "self-published@npm:@parcel/[email protected]":
name self-published
version "2.6.3-nightly.2759"
resolved "https://packages.atlassian.com/api/npm/npm-remote/@parcel/hash/-/hash-2.6.3-nightly.2759.tgz#79706adcae6dd7e0fa34c7724c8e1486e35c961c"
integrity sha512-//7MN5KujrEyKQtY53hC90mrCrd3CfA8PUPiBWMmgdSUM4pOlugDDNmspxghbhp8nftK12fGv0F6yfGnDy/k3A==
Expand Down Expand Up @@ -14187,8 +14189,8 @@ universal-user-agent@^4.0.0:

universal-user-agent@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee"
integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==
resolved "https://packages.atlassian.com/api/npm/npm-remote/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee"
integrity sha1-M4H4UDslHA2c0hvB3pOeyd9UgO4=

universalify@^0.1.0, universalify@^0.1.2:
version "0.1.2"
Expand Down

0 comments on commit 49f8205

Please sign in to comment.