Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,27 @@ jobs:

- name: Type-check
run: pnpm type-check

benchmark:
name: Benchmarks
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install pnpm
uses: pnpm/action-setup@v4.0.0

- name: Set node version to 20
uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://registry.npmjs.org/
cache: pnpm

- name: Install deps
run: pnpm install

- name: Run benchmarks
run: pnpm benchmark
62 changes: 62 additions & 0 deletions benchmarks/completion.bench.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Bench } from 'tinybench';
import { promisify } from 'node:util';
import { exec as execCb } from 'node:child_process';

const exec = promisify(execCb);

const bench = new Bench({ time: 2000 });

const cmdPrefix = `${process.execPath} ./dist/examples/demo.t.js complete --`;

async function run(cmd: string) {
await exec(cmd);
}

bench.add('command completion', async () => {
await run(`${cmdPrefix} d`);
});

bench.add('option completion', async () => {
await run(`${cmdPrefix} dev --p`);
});

bench.add('option value completion', async () => {
await run(`${cmdPrefix} dev --port ""`);
});

bench.add('config value completion', async () => {
await run(`${cmdPrefix} --config ""`);
});

bench.add('no match', async () => {
await run(`${cmdPrefix} xyz`);
});

async function runBenchmarks() {
await bench.run();

console.table(
bench.tasks.map((task) => {
const hz = task.result?.hz;
const derivedMs =
typeof hz === 'number' && hz > 0 ? 1000 / hz : undefined;
const mean = task.result?.mean;
return {
name: task.name,
'ops/sec': hz ? Math.round(hz).toLocaleString() : 'N/A',
'avg (ms)':
derivedMs !== undefined
? derivedMs.toFixed(3)
: mean !== undefined
? (mean * 1000).toFixed(3)
: 'N/A',
};
})
);
}

if (process.argv[1]?.endsWith('completion.bench.ts')) {
runBenchmarks().catch(console.error);
}

export { runBenchmarks };
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"build": "tsdown",
"prepare": "pnpm build",
"lint": "eslint src \"./*.ts\"",
"test-cli": "tsx bin/cli.ts"
"benchmark": "tsx benchmarks/completion.bench.ts"
},
"files": [
"dist"
Expand All @@ -30,6 +30,7 @@
"commander": "^13.1.0",
"eslint-config-prettier": "^10.0.1",
"prettier": "^3.5.2",
"tinybench": "^4.0.1",
"tsdown": "^0.9.7",
"tsx": "^4.19.1",
"typescript": "^5.7.3",
Expand Down
9 changes: 9 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions tsdown.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ export default defineConfig({
'src/cac.ts',
'src/commander.ts',
'bin/cli.ts',
'examples/demo.t.ts',
'examples/demo.cac.ts',
'examples/demo.citty.ts',
'examples/demo.commander.ts',
],
format: ['esm'],
dts: true,
Expand Down
Loading