adding a p-profiler that is independent of the underlying runner
This commit is contained in:
Родитель
252b5ec01c
Коммит
fd56bc606f
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "p-profiler",
|
||||
"version": "0.1.0",
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"start": "tsc -w --preserveWatchOutput",
|
||||
"test": "jest",
|
||||
"release": "yarn build && yarn test && beachball publish",
|
||||
"check": "beachball check",
|
||||
"change": "beachball change"
|
||||
},
|
||||
"repository": {
|
||||
"url": "https://github.com/microsoft/p-profiler"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^25.2.1",
|
||||
"@types/node": "^14.0.5",
|
||||
"beachball": "^1.31.0",
|
||||
"jest": "^25.5.3",
|
||||
"ts-jest": "^25.4.0",
|
||||
"typescript": "^3.8.3"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// Taken from https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview
|
||||
|
||||
export interface ProfilerEvent {
|
||||
/** The name of the event, as displayed in Trace Viewer */
|
||||
name: string;
|
||||
|
||||
/** The event categories. This is a comma separated list of categories for the event. The categories can be used to hide events in the Trace Viewer UI. */
|
||||
cat: string;
|
||||
|
||||
/** The event type. This is a single character which changes depending on the type of event being output. The valid values are listed in the table below. We will discuss each phase type below. */
|
||||
ph: string;
|
||||
|
||||
/** The tracing clock timestamp of the event. The timestamps are provided at microsecond granularity. */
|
||||
ts: number;
|
||||
|
||||
/** Optional. The thread clock timestamp of the event. The timestamps are provided at microsecond granularity. */
|
||||
tts?: string;
|
||||
|
||||
/** The procevss ID for the process that output this event. */
|
||||
pid: number;
|
||||
|
||||
/** The thread ID for the thread that output this event. */
|
||||
tid: number;
|
||||
|
||||
/** Any arguments provided for the event. Some of the event types have required argument fields, otherwise, you can put any information you wish in here. The arguments are displayed in Trace Viewer when you view an event in the analysis section. */
|
||||
args?: any;
|
||||
|
||||
/** duration */
|
||||
dur: number;
|
||||
|
||||
/** A fixed color name to associate with the event. If provided, cname must be one of the names listed in trace-viewer's base color scheme's reserved color names list */
|
||||
cname?: string;
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
// Prior art: https://github.com/lerna/lerna/blob/master/utils/profiler/profiler.js by @bweggersen
|
||||
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { ProfilerEvent } from "./ProfilerEvent";
|
||||
|
||||
const hrtimeToMicroseconds = (hrtime) => {
|
||||
return (hrtime[0] * 1e9 + hrtime[1]) / 1000;
|
||||
};
|
||||
|
||||
const range = (len) => {
|
||||
return Array(len)
|
||||
.fill(0)
|
||||
.map((_, idx) => idx);
|
||||
};
|
||||
|
||||
const getTimeBasedFilename = (prefix: string) => {
|
||||
const now = new Date(); // 2011-10-05T14:48:00.000Z
|
||||
const datetime = now.toISOString().split(".")[0]; // 2011-10-05T14:48:00
|
||||
const datetimeNormalized = datetime.replace(/-|:/g, ""); // 20111005T144800
|
||||
return `${prefix ? prefix + "-" : ""}${datetimeNormalized}.json`;
|
||||
};
|
||||
|
||||
export interface ProfilerOptions {
|
||||
concurrency: number;
|
||||
prefix: string;
|
||||
outDir: string;
|
||||
}
|
||||
|
||||
export class Profiler {
|
||||
private events: ProfilerEvent[];
|
||||
private outputPath: string;
|
||||
private threads: number[];
|
||||
|
||||
constructor(opts: ProfilerOptions) {
|
||||
const { concurrency, outDir, prefix } = opts;
|
||||
|
||||
this.events = [];
|
||||
this.outputPath = path.join(
|
||||
path.resolve(outDir || "."),
|
||||
getTimeBasedFilename(prefix)
|
||||
);
|
||||
this.threads = range(concurrency);
|
||||
}
|
||||
|
||||
run(fn: () => Promise<unknown>, name: string, cat?: string) {
|
||||
let startTime: [number, number];
|
||||
let threadId: number;
|
||||
|
||||
return Promise.resolve()
|
||||
.then(() => {
|
||||
startTime = process.hrtime();
|
||||
threadId = this.threads.shift();
|
||||
})
|
||||
.then(() => fn())
|
||||
.then((value) => {
|
||||
const duration = process.hrtime(startTime);
|
||||
|
||||
// Trace Event Format documentation:
|
||||
// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview
|
||||
const event: ProfilerEvent = {
|
||||
name,
|
||||
cat,
|
||||
ph: "X",
|
||||
ts: hrtimeToMicroseconds(startTime),
|
||||
pid: 1,
|
||||
tid: threadId,
|
||||
dur: hrtimeToMicroseconds(duration),
|
||||
};
|
||||
|
||||
this.events.push(event);
|
||||
|
||||
this.threads.unshift(threadId);
|
||||
this.threads.sort();
|
||||
|
||||
return value;
|
||||
});
|
||||
}
|
||||
|
||||
output() {
|
||||
return fs.writeFileSync(this.outputPath, JSON.stringify(this.events));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Profiler;
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"declaration": true,
|
||||
"module": "CommonJS",
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"lib": ["ES2017"],
|
||||
"outDir": "lib"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||
|
||||
name: PR
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: yarn
|
||||
- run: yarn checkchange
|
||||
- run: yarn build
|
||||
- run: yarn test
|
|
@ -0,0 +1,34 @@
|
|||
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
token: ${{ secrets.repo_pat }}
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: yarn
|
||||
- run: yarn build
|
||||
- run: yarn test
|
||||
- run: |
|
||||
git config user.email "kchau@microsoft.com"
|
||||
git config user.name "Ken Chau"
|
||||
- run: yarn release -y -n $NPM_AUTHTOKEN
|
||||
env:
|
||||
NPM_AUTHTOKEN: ${{ secrets.npm_authtoken }}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче