Skip to content

Commit

Permalink
Update README
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason3S committed Apr 19, 2024
1 parent 1dd4d3c commit 101c4a0
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 130 deletions.
133 changes: 54 additions & 79 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,85 +1,60 @@
# template-typescript-cli-app
# Perf Tests

A Repository Template for TypeScript Command Line Applications / Tools
This is a collection of perf tests. They are designed to check assumptions on performance.

This is a simple command line tool that lists files matching the provided globs.

## Getting Started

1. Install [`pnpm`](https://pnppm.io)

1. `pnpm i`

1. `pnpm test`

1. `pnpm run app --help`

<!--- @@inject: static/help.txt --->

```
Usage: list-files [options] <files...>
List Files
Arguments:
files Files to scan for injected content.
Options:
--no-must-find-files No error if files are not found.
--cwd <dir> Current Directory
--color Force color.
--no-color Do not use color.
-V, --version output the version number
-h, --help display help for command
```
<!--- @@inject-end: static/help.txt --->
1. `pnpm run app "*"`
**Example:**
<!--- @@inject: static/example.txt --->
```
Find Files:
- LICENSE
- README.md
- bin.mjs
- coverage
- cspell.config.yaml
- dist
- package.json
- pnpm-lock.yaml
- release-please-config.json
- scripts
- src
- static
- tsconfig.json
- vitest.config.ts
done.
```
<!--- @@inject-end: static/example.txt --->
## `pnpm` - this template uses pnpm.
See: https://pnpm.io/
## `vitest` - this template uses ViTest for testing.
See: https://vitest.dev/
## ES Modules
This tools is setup to use ES Modules.
## GitHub Workflows
This template includes GitHub Workflows for:
- testing
- code coverage
- lint
- release please (for generating releases)
- CodeQL
1. Install [`pnpm`](https://pnppm.io)
1. `pnpm i`
1. `pnpm build`
1. `pnpm test`
1. `pnpm run app --help`

<!--- @@inject: static/help.txt --->

```
Usage: perf runner [options] [test-methods...]
Run performance tests.
Arguments:
test-methods list of test methods to run (choices: "search",
"anonymous", "map", "all", default: ["all"])
Options:
-t, --timeout <timeout> timeout for each test (default: 1000)
-V, --version output the version number
-h, --help display help for command
```

<!--- @@inject-end: static/help.txt --->

1. `pnpm run app map`

**Example:**

<!--- @@inject: static/example.txt --->

```
Running test: map
Running: Map Anonymous:
✔ (a) => a.length : ops: 30756.44 cnt: 30482 mean: 0.056665 p95: 0.20633 min/max: 0.020739/ 1.2881 991.08ms
✔ filter Boolean : ops: 10380.80 cnt: 10339 mean: 0.14109 p95: 0.30647 min/max: 0.044631/ 0.65964 995.97ms
✔ filter (a) => a : ops: 14978.50 cnt: 14922 mean: 0.10100 p95: 0.23417 min/max: 0.038621/ 0.43152 996.23ms
✔ filter (a) => !!a : ops: 12926.77 cnt: 12883 mean: 0.11535 p95: 0.26402 min/max: 0.042264/ 0.71627 996.61ms
✔ (a) => { return a.length; }: ops: 31771.79 cnt: 31558 mean: 0.050315 p95: 0.13926 min/max: 0.021965/ 0.38313 993.27ms
✔ (fnLen) : ops: 29314.10 cnt: 29129 mean: 0.055057 p95: 0.15008 min/max: 0.021760/ 0.48103 993.69ms
✔ (a) => fnLen(a) : ops: 29233.77 cnt: 29043 mean: 0.055084 p95: 0.14469 min/max: 0.021979/ 0.37546 993.47ms
✔ (vfLen) : ops: 31732.97 cnt: 31525 mean: 0.051079 p95: 0.13862 min/max: 0.021709/ 0.36765 993.45ms
✔ for of : ops: 21886.60 cnt: 21765 mean: 0.061837 p95: 0.18468 min/max: 0.036873/ 1.0753 994.44ms
✔ for i : ops: 24704.07 cnt: 24556 mean: 0.051921 p95: 0.14648 min/max: 0.032250/ 0.64389 994.01ms
✔ for i r[i]=v : ops: 19494.68 cnt: 19400 mean: 0.065557 p95: 0.17119 min/max: 0.040939/ 0.49368 995.14ms
✔ for i Array.from(words) : ops: 33609.02 cnt: 33345 mean: 0.040022 p95: 0.12977 min/max: 0.025327/ 0.69438 992.14ms
✔ for i Array.from : ops: 2041.26 cnt: 2040 mean: 0.50531 p95: 0.70403 min/max: 0.43681/ 1.2301 999.38ms
✔ for i Array(size) : ops: 32333.11 cnt: 32082 mean: 0.056348 p95: 0.63695 min/max: 0.024706/ 6.5348 992.23ms
done.
```

<!--- @@inject-end: static/example.txt --->
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"build": "tsc -p .",
"build:readme": "pnpm build:readme:help && pnpm build:readme:example && pnpm build:readme:inject && prettier -w README.md",
"build:readme:help": "./bin.mjs --help > static/help.txt",
"build:readme:example": "./bin.mjs \"*\" > static/example.txt",
"build:readme:example": "./bin.mjs map > static/example.txt",
"build:readme:inject": "inject-markdown README.md",
"watch": "tsc -p . --watch",
"coverage": "vitest run --coverage",
Expand Down
60 changes: 34 additions & 26 deletions src/runner.mts
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,7 @@ interface ProgressReporting {
testStart?(name: string): void;
testEnd?(result: TestResult): void;
testIteration?(name: string, iteration: number, duration: number): void;
log?: typeof console.log;
error?: typeof console.error;
stderr?: typeof process.stderr;
stdout?: typeof process.stdout;
spinner?: Ora;
}
Expand All @@ -81,13 +79,13 @@ export async function runTests(
testWrapperFn: (context: RunnerContext) => void | Promise<void>,
progress?: ProgressReporting,
): Promise<RunnerResult> {
const log = progress?.log || console.log;
const stderr = progress?.stderr || process.stderr;
const spinner = progress?.spinner || ora({ stream: stderr });
const stdout = progress?.stdout || process.stdout;
const spinner = progress?.spinner || ora({ stream: stdout });
const log = (msg: string) => stdout.write(msg + '\n');

let nameWidth = 0;

const reportTestStart = progress?.testStart ?? ((name: string) => spinner.start(name));
const reportTestStart = progress?.testStart ?? ((name: string) => stdout.isTTY && spinner.start(name));
const reportTestEnd = (result: TestResult) => {
if (progress?.testEnd) {
if (spinner.isSpinning) {
Expand All @@ -96,34 +94,19 @@ export async function runTests(
return progress.testEnd(result);
}

const { name, duration, iterations, sd } = result;

const min = sd.min;
const max = sd.max;
const p95 = sd.ok ? sd.p95 : NaN;
const mean = sd.ok ? sd.mean : NaN;
const ops = (iterations * 1000) / duration;
const msg = formatResult(result, nameWidth);

if (spinner.isSpinning) {
if (result.error) {
spinner.fail(`${name} ${duration.toFixed(2)}ms`);
log('Error: %o', result.error);
spinner.fail(msg);
} else {
spinner.succeed(
`${name.padEnd(nameWidth)}: ` +
`ops: ${ops.toFixed(2).padStart(8)} ` +
`cnt: ${iterations.toFixed(0).padStart(6)} ` +
`mean: ${mean.toPrecision(5).padStart(8)} ` +
`p95: ${p95.toPrecision(5).padStart(8)} ` +
`min/max: ${min.toPrecision(5).padStart(8)}/${max.toPrecision(5).padStart(8)} ` +
`${duration.toFixed(2)}ms `,
);
spinner.succeed(msg);
}
} else {
if (result.error) {
log(`Test: ${name} finished in ${duration}ms with error: %o`, result.error);
log(`X ${msg}`);
} else {
log(`Test: ${name} finished in ${duration}ms`);
log(` ${msg}`);
}
}
};
Expand Down Expand Up @@ -248,6 +231,31 @@ function toError(e: unknown): Error {
return e instanceof Error ? e : new Error(String(e));
}

function formatResult(result: TestResult, nameWidth: number): string {
const { name, duration, iterations, sd } = result;

const min = sd.min;
const max = sd.max;
const p95 = sd.ok ? sd.p95 : NaN;
const mean = sd.ok ? sd.mean : NaN;
const ops = (iterations * 1000) / duration;

if (result.error) {
return `${name.padEnd(nameWidth)}: ${duration.toFixed(2)}ms\n` + `Error: ${result.error}`;
}

const msg =
`${name.padEnd(nameWidth)}: ` +
`ops: ${ops.toFixed(2).padStart(8)} ` +
`cnt: ${iterations.toFixed(0).padStart(6)} ` +
`mean: ${mean.toPrecision(5).padStart(8)} ` +
`p95: ${p95.toPrecision(5).padStart(8)} ` +
`min/max: ${min.toPrecision(5).padStart(8)}/${max.toPrecision(5).padStart(8)} ` +
`${duration.toFixed(2)}ms `;

return msg;
}

// function wait(time: number): Promise<void> {
// return new Promise((resolve) => setTimeout(resolve, time));
// }
31 changes: 16 additions & 15 deletions static/example.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
Find Files:
- LICENSE
- README.md
- bin.mjs
- coverage
- cspell.config.yaml
- dist
- package.json
- pnpm-lock.yaml
- release-please-config.json
- scripts
- src
- static
- tsconfig.json
- vitest.config.ts
Running test: map
Running: Map Anonymous:
✔ (a) => a.length : ops: 30756.44 cnt: 30482 mean: 0.056665 p95: 0.20633 min/max: 0.020739/ 1.2881 991.08ms
✔ filter Boolean : ops: 10380.80 cnt: 10339 mean: 0.14109 p95: 0.30647 min/max: 0.044631/ 0.65964 995.97ms
✔ filter (a) => a : ops: 14978.50 cnt: 14922 mean: 0.10100 p95: 0.23417 min/max: 0.038621/ 0.43152 996.23ms
✔ filter (a) => !!a : ops: 12926.77 cnt: 12883 mean: 0.11535 p95: 0.26402 min/max: 0.042264/ 0.71627 996.61ms
✔ (a) => { return a.length; }: ops: 31771.79 cnt: 31558 mean: 0.050315 p95: 0.13926 min/max: 0.021965/ 0.38313 993.27ms
✔ (fnLen) : ops: 29314.10 cnt: 29129 mean: 0.055057 p95: 0.15008 min/max: 0.021760/ 0.48103 993.69ms
✔ (a) => fnLen(a) : ops: 29233.77 cnt: 29043 mean: 0.055084 p95: 0.14469 min/max: 0.021979/ 0.37546 993.47ms
✔ (vfLen) : ops: 31732.97 cnt: 31525 mean: 0.051079 p95: 0.13862 min/max: 0.021709/ 0.36765 993.45ms
✔ for of : ops: 21886.60 cnt: 21765 mean: 0.061837 p95: 0.18468 min/max: 0.036873/ 1.0753 994.44ms
✔ for i : ops: 24704.07 cnt: 24556 mean: 0.051921 p95: 0.14648 min/max: 0.032250/ 0.64389 994.01ms
✔ for i r[i]=v : ops: 19494.68 cnt: 19400 mean: 0.065557 p95: 0.17119 min/max: 0.040939/ 0.49368 995.14ms
✔ for i Array.from(words) : ops: 33609.02 cnt: 33345 mean: 0.040022 p95: 0.12977 min/max: 0.025327/ 0.69438 992.14ms
✔ for i Array.from : ops: 2041.26 cnt: 2040 mean: 0.50531 p95: 0.70403 min/max: 0.43681/ 1.2301 999.38ms
✔ for i Array(size) : ops: 32333.11 cnt: 32082 mean: 0.056348 p95: 0.63695 min/max: 0.024706/ 6.5348 992.23ms
done.
16 changes: 7 additions & 9 deletions static/help.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
Usage: list-files [options] <files...>
Usage: perf runner [options] [test-methods...]

List Files
Run performance tests.

Arguments:
files Files to scan for injected content.
test-methods list of test methods to run (choices: "search",
"anonymous", "map", "all", default: ["all"])

Options:
--no-must-find-files No error if files are not found.
--cwd <dir> Current Directory
--color Force color.
--no-color Do not use color.
-V, --version output the version number
-h, --help display help for command
-t, --timeout <timeout> timeout for each test (default: 1000)
-V, --version output the version number
-h, --help display help for command

0 comments on commit 101c4a0

Please sign in to comment.