Skip to content
Open
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
83 changes: 78 additions & 5 deletions src/write.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,85 @@ function floatStr(n: number) {
return n.toString();
}

function strVal(b: BenchmarkResult): string {
let s = `\`${b.value}\` ${b.unit}`;
if (b.range) {
s += ` (\`${b.range}\`)`;
const round = (n: number, places = 3): number => parseFloat(n.toFixed(places));

function strDuration(n: number): string {
let unit = 'ns';
if (n >= 6e10) {
let secs = n / 1e9;
const mins = Math.floor(secs / 60);
secs %= 60;
return `${mins}m ${round(secs)}s`;
}

if (n >= 1e9) {
unit = 's';
n /= 1e9;
} else if (n >= 1e6) {
unit = 'ms';
n /= 1e6;
} else if (n >= 1e3) {
unit = 'μs';
n /= 1e3;
}

return `${round(n)}${unit}`;
}

const NS_PER_TIME_UNIT: { [unit: string]: number } = {
ns: 1,
us: 1e3,
ms: 1e6,
s: 1e9,
};

interface DurationFormat {
timeUnit: string;
suffix: string;
}

function parseDurationFormat(unit: string): DurationFormat | null {
const perIter = unit.match(/^(ns|us|ms|s)\/(\w+)$/);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
if (perIter) {
return { timeUnit: perIter[1], suffix: `/${perIter[2]}` };
}
return s;

const duration = unit.match(/^(ns|us|ms|s)$/);
if (duration) {
return { timeUnit: duration[1], suffix: '' };
}

return null;
}

function toNanoseconds(value: number, timeUnit: string): number {
return value * NS_PER_TIME_UNIT[timeUnit];
}

const RANGE_REGEX = /^±\s*(\d+(?:\.\d+)?)$/;

function strRange(range: string | undefined, timeUnit: string): string | undefined {
const m = range?.match(RANGE_REGEX);
if (!m) {
return range;
}
return '± ' + strDuration(toNanoseconds(parseFloat(m[1]), timeUnit));
}

function strRawValue(b: BenchmarkResult): string {
const value = `\`${b.value} ${b.unit}\``;
return b.range ? `${value}<br>(\`${b.range}\`)` : value;
}

function strDurationValue(b: BenchmarkResult, format: DurationFormat): string {
const value = `\`${strDuration(toNanoseconds(b.value, format.timeUnit))}${format.suffix}\``;
const range = strRange(b.range, format.timeUnit);
return range ? `${value}<br>(\`${range}\`)` : value;
}

function strVal(b: BenchmarkResult): string {
const duration = parseDurationFormat(b.unit);
return duration === null ? strRawValue(b) : strDurationValue(b, duration);
}

function commentFooter(): string {
Expand Down
76 changes: 70 additions & 6 deletions test/buildComment.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { buildComment } from '../src/write';
import { Benchmark, BenchmarkResult } from '../src/extract';
import { FakedOctokit, fakedRepos } from './fakedOctokit';
import dedent from 'dedent';

Expand Down Expand Up @@ -111,9 +112,9 @@ describe('buildComment', () => {

| Benchmark suite | Current: testCommitIdCurrent | Previous: testCommitIdPrevious | Ratio |
|-|-|-|-|
| \`TestBench<1>\` | \`0\` testUnit | \`0\` testUnit | \`1\` |
| \`TestBench<2>\` | \`1\` testUnit | \`0\` testUnit | \`+∞\` |
| \`TestBench<3>\` | \`-1\` testUnit | \`0\` testUnit | \`-∞\` |
| \`TestBench<1>\` | \`0 testUnit\` | \`0 testUnit\` | \`1\` |
| \`TestBench<2>\` | \`1 testUnit\` | \`0 testUnit\` | \`+∞\` |
| \`TestBench<3>\` | \`-1 testUnit\` | \`0 testUnit\` | \`-∞\` |

</details>

Expand Down Expand Up @@ -197,13 +198,76 @@ describe('buildComment', () => {

| Benchmark suite | Current: testCommitIdCurrent | Previous: testCommitIdPrevious | Ratio |
|-|-|-|-|
| \`TestBench<1>\` | \`0\` testUnit | \`0\` testUnit | \`1\` |
| \`TestBench<2>\` | \`0\` testUnit | \`1\` testUnit | \`+∞\` |
| \`TestBench<3>\` | \`0\` testUnit | \`-1\` testUnit | \`-∞\` |
| \`TestBench<1>\` | \`0 testUnit\` | \`0 testUnit\` | \`1\` |
| \`TestBench<2>\` | \`0 testUnit\` | \`1 testUnit\` | \`+∞\` |
| \`TestBench<3>\` | \`0 testUnit\` | \`-1 testUnit\` | \`-∞\` |

</details>

This comment was automatically generated by [workflow](https://github.com/user/repo/actions?query=workflow%3AWorkflow%20name) using [github-action-benchmark](https://github.com/marketplace/actions/continuous-benchmark).
`);
});

describe('value formatting', () => {
function suite(bench: BenchmarkResult): Benchmark {
return {
date: 12345,
commit: {
id: 'testCommitId',
author: { name: 'TestUser' },
committer: { name: 'TestUser' },
message: 'Test commit message',
url: 'https://test.commit.url',
},
tool: 'customSmallerIsBetter',
benches: [bench],
};
}

function renderValue(bench: BenchmarkResult): string {
const comment = buildComment('TestSuite', suite(bench), suite(bench), false);
const line = comment.split('\n').find((l) => l.startsWith('| `bench`'));
if (line === undefined) {
throw new Error(`Benchmark row not found in comment:\n${comment}`);
}
return line.split('|')[2].trim();
}

const cases: Array<[string, BenchmarkResult, string]> = [
['bare nanoseconds', { name: 'bench', value: 25000, unit: 'ns' }, '`25μs`'],
['bare microseconds', { name: 'bench', value: 25000, unit: 'us' }, '`25ms`'],
['bare milliseconds', { name: 'bench', value: 25000, unit: 'ms' }, '`25s`'],
['bare seconds', { name: 'bench', value: 100, unit: 's' }, '`1m 40s`'],
['nanoseconds per iteration', { name: 'bench', value: 25000, unit: 'ns/iter' }, '`25μs/iter`'],
['microseconds per iteration', { name: 'bench', value: 25000, unit: 'us/iter' }, '`25ms/iter`'],
['nanoseconds per op', { name: 'bench', value: 25000, unit: 'ns/op' }, '`25μs/op`'],
[
'range in nanoseconds',
{ name: 'bench', value: 25000, unit: 'ns/iter', range: '± 1000' },
'`25μs/iter`<br>(`± 1μs`)',
],
[
'range in microseconds',
{ name: 'bench', value: 25000, unit: 'us/iter', range: '± 1.5' },
'`25ms/iter`<br>(`± 1.5μs`)',
],
[
'unrecognized range is unchanged',
{ name: 'bench', value: 25000, unit: 'ns/iter', range: '± 2%' },
'`25μs/iter`<br>(`± 2%`)',
],
['unknown unit is unchanged', { name: 'bench', value: 5, unit: 'testUnit' }, '`5 testUnit`'],
[
'unsupported time unit is unchanged',
{ name: 'bench', value: 20, unit: 'ops/sec', range: '+-20' },
'`20 ops/sec`<br>(`+-20`)',
],
];

for (const [description, bench, expected] of cases) {
it(`formats ${description}`, () => {
expect(renderValue(bench)).toBe(expected);
});
}
});
});
26 changes: 13 additions & 13 deletions test/write.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -415,8 +415,8 @@ describe.each(['https://github.com', 'https://github.enterprise.corp'])('writeBe
'',
'| Benchmark suite | Current: current commit id | Previous: prev commit id | Ratio |',
'|-|-|-|-|',
'| `bench_fib_10` | `210` ns/iter (`± 20`) | `100` ns/iter (`± 20`) | `2.10` |',
'| `bench_fib_20` | `25000` ns/iter (`± 20`) | `10000` ns/iter (`± 20`) | `2.50` |',
'| `bench_fib_10` | `210ns/iter`<br>(`± 20ns`) | `100ns/iter`<br>(`± 20ns`) | `2.10` |',
'| `bench_fib_20` | `25μs/iter`<br>(`± 20ns`) | `10μs/iter`<br>(`± 20ns`) | `2.50` |',
'',
`This comment was automatically generated by [workflow](${serverUrl}/user/repo/actions?query=workflow%3AWorkflow%20name) using [github-action-benchmark](https://github.com/marketplace/actions/continuous-benchmark).`,
'',
Expand Down Expand Up @@ -463,8 +463,8 @@ describe.each(['https://github.com', 'https://github.enterprise.corp'])('writeBe
'',
'| Benchmark suite | Current: current commit id | Previous: prev commit id | Ratio |',
'|-|-|-|-|',
'| `bench_fib_10` | `210` ns/iter (`± 20`) | `100` ns/iter (`± 20`) | `2.10` |',
'| `bench_fib_20` | `2250` ns/iter (`± 20`) | `900` ns/iter (`± 20`) | `2.50` |',
'| `bench_fib_10` | `210ns/iter`<br>(`± 20ns`) | `100ns/iter`<br>(`± 20ns`) | `2.10` |',
'| `bench_fib_20` | `2.25μs/iter`<br>(`± 20ns`) | `900ns/iter`<br>(`± 20ns`) | `2.50` |',
'',
`This comment was automatically generated by [workflow](${serverUrl}/user/repo/actions?query=workflow%3AWorkflow%20name) using [github-action-benchmark](https://github.com/marketplace/actions/continuous-benchmark).`,
'',
Expand Down Expand Up @@ -502,7 +502,7 @@ describe.each(['https://github.com', 'https://github.enterprise.corp'])('writeBe
'',
'| Benchmark suite | Current: current commit id | Previous: prev commit id | Ratio |',
'|-|-|-|-|',
'| `benchFib10` | `20` ops/sec (`+-20`) | `100` ops/sec (`+-20`) | `5` |',
'| `benchFib10` | `20 ops/sec`<br>(`+-20`) | `100 ops/sec`<br>(`+-20`) | `5` |',
'',
`This comment was automatically generated by [workflow](${serverUrl}/user/repo/actions?query=workflow%3AWorkflow%20name) using [github-action-benchmark](https://github.com/marketplace/actions/continuous-benchmark).`,
'',
Expand Down Expand Up @@ -540,7 +540,7 @@ describe.each(['https://github.com', 'https://github.enterprise.corp'])('writeBe
'',
'| Benchmark suite | Current: current commit id | Previous: prev commit id | Ratio |',
'|-|-|-|-|',
'| `bench_fib_10` | `210` ns/iter (`± 20`) | `100` ns/iter (`± 20`) | `2.10` |',
'| `bench_fib_10` | `210ns/iter`<br>(`± 20ns`) | `100ns/iter`<br>(`± 20ns`) | `2.10` |',
'',
`This comment was automatically generated by [workflow](${serverUrl}/user/repo/actions?query=workflow%3AWorkflow%20name) using [github-action-benchmark](https://github.com/marketplace/actions/continuous-benchmark).`,
'',
Expand Down Expand Up @@ -578,7 +578,7 @@ describe.each(['https://github.com', 'https://github.enterprise.corp'])('writeBe
'',
'| Benchmark suite | Current: current commit id | Previous: prev commit id | Ratio |',
'|-|-|-|-|',
'| `bench_fib_10` | `210` ns/iter (`± 20`) | `100` ns/iter (`± 20`) | `2.10` |',
'| `bench_fib_10` | `210ns/iter`<br>(`± 20ns`) | `100ns/iter`<br>(`± 20ns`) | `2.10` |',
'',
`This comment was automatically generated by [workflow](${serverUrl}/user/repo/actions?query=workflow%3AWorkflow%20name) using [github-action-benchmark](https://github.com/marketplace/actions/continuous-benchmark).`,
],
Expand Down Expand Up @@ -719,8 +719,8 @@ describe.each(['https://github.com', 'https://github.enterprise.corp'])('writeBe
'',
'| Benchmark suite | Current: current commit id | Previous: prev commit id | Ratio |',
'|-|-|-|-|',
'| `bench_fib_10` | `210` ns/iter (`± 20`) | `100` ns/iter (`± 20`) | `2.10` |',
'| `bench_fib_20` | `25000` ns/iter (`± 20`) | `10000` ns/iter (`± 20`) | `2.50` |',
'| `bench_fib_10` | `210ns/iter`<br>(`± 20ns`) | `100ns/iter`<br>(`± 20ns`) | `2.10` |',
'| `bench_fib_20` | `25μs/iter`<br>(`± 20ns`) | `10μs/iter`<br>(`± 20ns`) | `2.50` |',
'',
`This comment was automatically generated by [workflow](${serverUrl}/user/repo/actions?query=workflow%3AWorkflow%20name) using [github-action-benchmark](https://github.com/marketplace/actions/continuous-benchmark).`,
'',
Expand Down Expand Up @@ -758,7 +758,7 @@ describe.each(['https://github.com', 'https://github.enterprise.corp'])('writeBe
'',
'| Benchmark suite | Current: current commit id | Previous: prev commit id | Ratio |',
'|-|-|-|-|',
'| `benchFib10` | `100` ops/sec (`+-20`) | `100` ops/sec (`+-20`) | `1` |',
'| `benchFib10` | `100 ops/sec`<br>(`+-20`) | `100 ops/sec`<br>(`+-20`) | `1` |',
'',
`This comment was automatically generated by [workflow](${serverUrl}/user/repo/actions?query=workflow%3AWorkflow%20name) using [github-action-benchmark](https://github.com/marketplace/actions/continuous-benchmark).`,
'',
Expand Down Expand Up @@ -798,7 +798,7 @@ describe.each(['https://github.com', 'https://github.enterprise.corp'])('writeBe
'',
'| Benchmark suite | Current: current commit id | Previous: prev commit id | Ratio |',
'|-|-|-|-|',
'| `bench_fib_10` | `350` ns/iter (`± 20`) | `100` ns/iter (`± 20`) | `3.50` |',
'| `bench_fib_10` | `350ns/iter`<br>(`± 20ns`) | `100ns/iter`<br>(`± 20ns`) | `3.50` |',
'',
`This comment was automatically generated by [workflow](${serverUrl}/user/repo/actions?query=workflow%3AWorkflow%20name) using [github-action-benchmark](https://github.com/marketplace/actions/continuous-benchmark).`,
'',
Expand Down Expand Up @@ -1243,7 +1243,7 @@ describe.each(['https://github.com', 'https://github.enterprise.corp'])('writeBe
'',
'| Benchmark suite | Current: current commit id | Previous: prev commit id | Ratio |',
'|-|-|-|-|',
'| `bench_fib_10` | `210` ns/iter (`± 20`) | `100` ns/iter (`± 20`) | `2.10` |',
'| `bench_fib_10` | `210ns/iter`<br>(`± 20ns`) | `100ns/iter`<br>(`± 20ns`) | `2.10` |',
'',
`This comment was automatically generated by [workflow](${serverUrl}/user/repo/actions?query=workflow%3AWorkflow%20name) using [github-action-benchmark](https://github.com/marketplace/actions/continuous-benchmark).`,
],
Expand All @@ -1267,7 +1267,7 @@ describe.each(['https://github.com', 'https://github.enterprise.corp'])('writeBe
'',
'| Benchmark suite | Current: current commit id | Previous: prev commit id | Ratio |',
'|-|-|-|-|',
'| `bench_fib_10` | `210` ns/iter (`± 20`) | `100` ns/iter (`± 20`) | `2.10` |',
'| `bench_fib_10` | `210ns/iter`<br>(`± 20ns`) | `100ns/iter`<br>(`± 20ns`) | `2.10` |',
'',
`This comment was automatically generated by [workflow](${serverUrl}/user/repo/actions?query=workflow%3AWorkflow%20name) using [github-action-benchmark](https://github.com/marketplace/actions/continuous-benchmark).`,
],
Expand Down
Loading