Skip to content

Commit 4f0408d

Browse files
authoredSep 25, 2020
Run 4 perf tests instead of 2 (#80)
* Run Prettier * Average over four tests instead of two * More advanced algorithm * spelling * Return the results * Update index.js * Update index.js
1 parent 42ae818 commit 4f0408d

File tree

4 files changed

+378
-338
lines changed

4 files changed

+378
-338
lines changed
 

Diff for: ‎.github/workflows/perf.yml

+16-16
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@ jobs:
66
perf:
77
runs-on: Ubuntu-18.04
88
steps:
9-
- name: Checkout
10-
uses: actions/checkout@master
11-
with:
12-
fetch-depth: 1
13-
- name: Run Benchmark
14-
run: |
15-
git clone https://github.com/kylef/swiftenv.git ~/.swiftenv
16-
export SWIFTENV_ROOT="$HOME/.swiftenv"
17-
export PATH="$SWIFTENV_ROOT/bin:$PATH"
18-
eval "$(swiftenv init -)"
19-
swiftenv install $TOOLCHAIN_DOWNLOAD
20-
make perf-tester
21-
node ci/perf-tester
22-
env:
23-
TOOLCHAIN_DOWNLOAD: https://github.com/swiftwasm/swift/releases/download/swift-wasm-5.3-SNAPSHOT-2020-08-10-a/swift-wasm-5.3-SNAPSHOT-2020-08-10-a-linux.tar.gz
24-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
9+
- name: Checkout
10+
uses: actions/checkout@master
11+
with:
12+
fetch-depth: 1
13+
- name: Run Benchmark
14+
run: |
15+
git clone https://github.com/kylef/swiftenv.git ~/.swiftenv
16+
export SWIFTENV_ROOT="$HOME/.swiftenv"
17+
export PATH="$SWIFTENV_ROOT/bin:$PATH"
18+
eval "$(swiftenv init -)"
19+
swiftenv install $TOOLCHAIN_DOWNLOAD
20+
make perf-tester
21+
node ci/perf-tester
22+
env:
23+
TOOLCHAIN_DOWNLOAD: https://github.com/swiftwasm/swift/releases/download/swift-wasm-5.3-SNAPSHOT-2020-08-10-a/swift-wasm-5.3-SNAPSHOT-2020-08-10-a-linux.tar.gz
24+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Diff for: ‎CHANGELOG.md

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# Unreleased
22

3-
43
# 0.7.0 (25 September 2020)
54

65
This release adds multiple new types bridged from JavaScript, namely `JSError`, `JSDate`, `JSTimer` (which corresponds to `setTimeout`/`setInterval` calls and manages closure lifetime for you), `JSString` and `JSPromise`. We now also have [documentation published automatically](https://swiftwasm.github.io/JavaScriptKit/) for the main branch.

Diff for: ‎ci/perf-tester/src/index.js

+219-188
Original file line numberDiff line numberDiff line change
@@ -20,206 +20,237 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2020
SOFTWARE.
2121
*/
2222

23-
const { setFailed, startGroup, endGroup, debug } = require('@actions/core');
24-
const { GitHub, context } = require('@actions/github');
25-
const { exec } = require('@actions/exec');
26-
const { getInput, runBenchmark, averageBenchmarks, toDiff, diffTable, toBool } = require('./utils.js');
23+
const { setFailed, startGroup, endGroup, debug } = require("@actions/core");
24+
const { GitHub, context } = require("@actions/github");
25+
const { exec } = require("@actions/exec");
26+
const {
27+
getInput,
28+
runBenchmark,
29+
averageBenchmarks,
30+
toDiff,
31+
diffTable,
32+
toBool,
33+
} = require("./utils.js");
34+
35+
const benchmarkParallel = 2;
36+
const benchmarkSerial = 2;
37+
const runBenchmarks = async () => {
38+
let results = [];
39+
for (let i = 0; i < benchmarkSerial; i++) {
40+
results = results.concat(
41+
await Promise.all(Array(benchmarkParallel).fill().map(runBenchmark))
42+
);
43+
}
44+
return averageBenchmarks(results);
45+
};
2746

2847
async function run(octokit, context, token) {
29-
const { number: pull_number } = context.issue;
30-
31-
const pr = context.payload.pull_request;
32-
try {
33-
debug('pr' + JSON.stringify(pr, null, 2));
34-
} catch (e) { }
35-
if (!pr) {
36-
throw Error('Could not retrieve PR information. Only "pull_request" triggered workflows are currently supported.');
37-
}
38-
39-
console.log(`PR #${pull_number} is targetted at ${pr.base.ref} (${pr.base.sha})`);
40-
41-
const buildScript = getInput('build-script');
42-
startGroup(`[current] Build using '${buildScript}'`);
43-
await exec(buildScript);
44-
endGroup();
45-
46-
startGroup(`[current] Running benchmark`);
47-
const newBenchmarks = await Promise.all([runBenchmark(), runBenchmark()]).then(averageBenchmarks);
48-
endGroup();
49-
50-
startGroup(`[base] Checkout target branch`);
51-
let baseRef;
52-
try {
53-
baseRef = context.payload.base.ref;
54-
if (!baseRef) throw Error('missing context.payload.pull_request.base.ref');
55-
await exec(`git fetch -n origin ${context.payload.pull_request.base.ref}`);
56-
console.log('successfully fetched base.ref');
57-
} catch (e) {
58-
console.log('fetching base.ref failed', e.message);
59-
try {
60-
await exec(`git fetch -n origin ${pr.base.sha}`);
61-
console.log('successfully fetched base.sha');
62-
} catch (e) {
63-
console.log('fetching base.sha failed', e.message);
64-
try {
65-
await exec(`git fetch -n`);
66-
} catch (e) {
67-
console.log('fetch failed', e.message);
68-
}
69-
}
70-
}
71-
72-
console.log('checking out and building base commit');
73-
try {
74-
if (!baseRef) throw Error('missing context.payload.base.ref');
75-
await exec(`git reset --hard ${baseRef}`);
76-
}
77-
catch (e) {
78-
await exec(`git reset --hard ${pr.base.sha}`);
79-
}
80-
endGroup();
81-
82-
startGroup(`[base] Build using '${buildScript}'`);
83-
await exec(buildScript);
84-
endGroup();
85-
86-
startGroup(`[base] Running benchmark`);
87-
const oldBenchmarks = await Promise.all([runBenchmark(), runBenchmark()]).then(averageBenchmarks);
88-
endGroup();
89-
90-
const diff = toDiff(oldBenchmarks, newBenchmarks);
91-
92-
const markdownDiff = diffTable(diff, {
93-
collapseUnchanged: true,
94-
omitUnchanged: false,
95-
showTotal: true,
96-
minimumChangeThreshold: parseInt(getInput('minimum-change-threshold'), 10)
97-
});
98-
99-
let outputRawMarkdown = false;
100-
101-
const commentInfo = {
102-
...context.repo,
103-
issue_number: pull_number
104-
};
105-
106-
const comment = {
107-
...commentInfo,
108-
body: markdownDiff + '\n\n<a href="https://github.com/j-f1/performance-action"><sub>performance-action</sub></a>'
109-
};
110-
111-
if (toBool(getInput('use-check'))) {
112-
if (token) {
113-
const finish = await createCheck(octokit, context);
114-
await finish({
115-
conclusion: 'success',
116-
output: {
117-
title: `Compressed Size Action`,
118-
summary: markdownDiff
119-
}
120-
});
121-
}
122-
else {
123-
outputRawMarkdown = true;
124-
}
125-
}
126-
else {
127-
startGroup(`Updating stats PR comment`);
128-
let commentId;
129-
try {
130-
const comments = (await octokit.issues.listComments(commentInfo)).data;
131-
for (let i = comments.length; i--;) {
132-
const c = comments[i];
133-
if (c.user.type === 'Bot' && /<sub>[\s\n]*performance-action/.test(c.body)) {
134-
commentId = c.id;
135-
break;
136-
}
137-
}
138-
}
139-
catch (e) {
140-
console.log('Error checking for previous comments: ' + e.message);
141-
}
142-
143-
if (commentId) {
144-
console.log(`Updating previous comment #${commentId}`)
145-
try {
146-
await octokit.issues.updateComment({
147-
...context.repo,
148-
comment_id: commentId,
149-
body: comment.body
150-
});
151-
}
152-
catch (e) {
153-
console.log('Error editing previous comment: ' + e.message);
154-
commentId = null;
155-
}
156-
}
157-
158-
// no previous or edit failed
159-
if (!commentId) {
160-
console.log('Creating new comment');
161-
try {
162-
await octokit.issues.createComment(comment);
163-
} catch (e) {
164-
console.log(`Error creating comment: ${e.message}`);
165-
console.log(`Submitting a PR review comment instead...`);
166-
try {
167-
const issue = context.issue || pr;
168-
await octokit.pulls.createReview({
169-
owner: issue.owner,
170-
repo: issue.repo,
171-
pull_number: issue.number,
172-
event: 'COMMENT',
173-
body: comment.body
174-
});
175-
} catch (e) {
176-
console.log('Error creating PR review.');
177-
outputRawMarkdown = true;
178-
}
179-
}
180-
}
181-
endGroup();
182-
}
183-
184-
if (outputRawMarkdown) {
185-
console.log(`
48+
const { number: pull_number } = context.issue;
49+
50+
const pr = context.payload.pull_request;
51+
try {
52+
debug("pr" + JSON.stringify(pr, null, 2));
53+
} catch (e) {}
54+
if (!pr) {
55+
throw Error(
56+
'Could not retrieve PR information. Only "pull_request" triggered workflows are currently supported.'
57+
);
58+
}
59+
60+
console.log(
61+
`PR #${pull_number} is targetted at ${pr.base.ref} (${pr.base.sha})`
62+
);
63+
64+
const buildScript = getInput("build-script");
65+
startGroup(`[current] Build using '${buildScript}'`);
66+
await exec(buildScript);
67+
endGroup();
68+
69+
startGroup(`[current] Running benchmark`);
70+
const newBenchmarks = await runBenchmarks();
71+
endGroup();
72+
73+
startGroup(`[base] Checkout target branch`);
74+
let baseRef;
75+
try {
76+
baseRef = context.payload.base.ref;
77+
if (!baseRef)
78+
throw Error("missing context.payload.pull_request.base.ref");
79+
await exec(
80+
`git fetch -n origin ${context.payload.pull_request.base.ref}`
81+
);
82+
console.log("successfully fetched base.ref");
83+
} catch (e) {
84+
console.log("fetching base.ref failed", e.message);
85+
try {
86+
await exec(`git fetch -n origin ${pr.base.sha}`);
87+
console.log("successfully fetched base.sha");
88+
} catch (e) {
89+
console.log("fetching base.sha failed", e.message);
90+
try {
91+
await exec(`git fetch -n`);
92+
} catch (e) {
93+
console.log("fetch failed", e.message);
94+
}
95+
}
96+
}
97+
98+
console.log("checking out and building base commit");
99+
try {
100+
if (!baseRef) throw Error("missing context.payload.base.ref");
101+
await exec(`git reset --hard ${baseRef}`);
102+
} catch (e) {
103+
await exec(`git reset --hard ${pr.base.sha}`);
104+
}
105+
endGroup();
106+
107+
startGroup(`[base] Build using '${buildScript}'`);
108+
await exec(buildScript);
109+
endGroup();
110+
111+
startGroup(`[base] Running benchmark`);
112+
const oldBenchmarks = await runBenchmarks();
113+
endGroup();
114+
115+
const diff = toDiff(oldBenchmarks, newBenchmarks);
116+
117+
const markdownDiff = diffTable(diff, {
118+
collapseUnchanged: true,
119+
omitUnchanged: false,
120+
showTotal: true,
121+
minimumChangeThreshold: parseInt(
122+
getInput("minimum-change-threshold"),
123+
10
124+
),
125+
});
126+
127+
let outputRawMarkdown = false;
128+
129+
const commentInfo = {
130+
...context.repo,
131+
issue_number: pull_number,
132+
};
133+
134+
const comment = {
135+
...commentInfo,
136+
body:
137+
markdownDiff +
138+
'\n\n<a href="https://github.com/j-f1/performance-action"><sub>performance-action</sub></a>',
139+
};
140+
141+
if (toBool(getInput("use-check"))) {
142+
if (token) {
143+
const finish = await createCheck(octokit, context);
144+
await finish({
145+
conclusion: "success",
146+
output: {
147+
title: `Compressed Size Action`,
148+
summary: markdownDiff,
149+
},
150+
});
151+
} else {
152+
outputRawMarkdown = true;
153+
}
154+
} else {
155+
startGroup(`Updating stats PR comment`);
156+
let commentId;
157+
try {
158+
const comments = (await octokit.issues.listComments(commentInfo))
159+
.data;
160+
for (let i = comments.length; i--; ) {
161+
const c = comments[i];
162+
if (
163+
c.user.type === "Bot" &&
164+
/<sub>[\s\n]*performance-action/.test(c.body)
165+
) {
166+
commentId = c.id;
167+
break;
168+
}
169+
}
170+
} catch (e) {
171+
console.log("Error checking for previous comments: " + e.message);
172+
}
173+
174+
if (commentId) {
175+
console.log(`Updating previous comment #${commentId}`);
176+
try {
177+
await octokit.issues.updateComment({
178+
...context.repo,
179+
comment_id: commentId,
180+
body: comment.body,
181+
});
182+
} catch (e) {
183+
console.log("Error editing previous comment: " + e.message);
184+
commentId = null;
185+
}
186+
}
187+
188+
// no previous or edit failed
189+
if (!commentId) {
190+
console.log("Creating new comment");
191+
try {
192+
await octokit.issues.createComment(comment);
193+
} catch (e) {
194+
console.log(`Error creating comment: ${e.message}`);
195+
console.log(`Submitting a PR review comment instead...`);
196+
try {
197+
const issue = context.issue || pr;
198+
await octokit.pulls.createReview({
199+
owner: issue.owner,
200+
repo: issue.repo,
201+
pull_number: issue.number,
202+
event: "COMMENT",
203+
body: comment.body,
204+
});
205+
} catch (e) {
206+
console.log("Error creating PR review.");
207+
outputRawMarkdown = true;
208+
}
209+
}
210+
}
211+
endGroup();
212+
}
213+
214+
if (outputRawMarkdown) {
215+
console.log(
216+
`
186217
Error: performance-action was unable to comment on your PR.
187218
This can happen for PR's originating from a fork without write permissions.
188219
You can copy the size table directly into a comment using the markdown below:
189220
\n\n${comment.body}\n\n
190-
`.replace(/^(\t| )+/gm, ''));
191-
}
221+
`.replace(/^(\t| )+/gm, "")
222+
);
223+
}
192224

193-
console.log('All done!');
225+
console.log("All done!");
194226
}
195227

196-
197228
// create a check and return a function that updates (completes) it
198229
async function createCheck(octokit, context) {
199-
const check = await octokit.checks.create({
200-
...context.repo,
201-
name: 'Compressed Size',
202-
head_sha: context.payload.pull_request.head.sha,
203-
status: 'in_progress',
204-
});
205-
206-
return async details => {
207-
await octokit.checks.update({
208-
...context.repo,
209-
check_run_id: check.data.id,
210-
completed_at: new Date().toISOString(),
211-
status: 'completed',
212-
...details
213-
});
214-
};
230+
const check = await octokit.checks.create({
231+
...context.repo,
232+
name: "Compressed Size",
233+
head_sha: context.payload.pull_request.head.sha,
234+
status: "in_progress",
235+
});
236+
237+
return async (details) => {
238+
await octokit.checks.update({
239+
...context.repo,
240+
check_run_id: check.data.id,
241+
completed_at: new Date().toISOString(),
242+
status: "completed",
243+
...details,
244+
});
245+
};
215246
}
216247

217248
(async () => {
218-
try {
219-
const token = getInput('repo-token', { required: true });
220-
const octokit = new GitHub(token);
221-
await run(octokit, context, token);
222-
} catch (e) {
223-
setFailed(e.message);
224-
}
249+
try {
250+
const token = getInput("repo-token", { required: true });
251+
const octokit = new GitHub(token);
252+
await run(octokit, context, token);
253+
} catch (e) {
254+
setFailed(e.message);
255+
}
225256
})();

Diff for: ‎ci/perf-tester/src/utils.js

+143-133
Original file line numberDiff line numberDiff line change
@@ -20,125 +20,130 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2020
SOFTWARE.
2121
*/
2222

23-
const fs = require('fs');
24-
const { exec } = require('@actions/exec');
25-
26-
const getInput = key => ({
27-
'build-script': 'make bootstrap benchmark_setup',
28-
benchmark: 'make -s run_benchmark',
29-
'minimum-change-threshold': 5,
30-
'use-check': 'no',
31-
'repo-token': process.env.GITHUB_TOKEN
32-
})[key]
33-
exports.getInput = getInput
23+
const fs = require("fs");
24+
const { exec } = require("@actions/exec");
25+
26+
const getInput = (key) =>
27+
({
28+
"build-script": "make bootstrap benchmark_setup",
29+
benchmark: "make -s run_benchmark",
30+
"minimum-change-threshold": 5,
31+
"use-check": "no",
32+
"repo-token": process.env.GITHUB_TOKEN,
33+
}[key]);
34+
exports.getInput = getInput;
3435

3536
exports.runBenchmark = async () => {
36-
let benchmarkBuffers = []
37-
await exec(getInput('benchmark'), [], {
38-
listeners: {
39-
stdout: data => benchmarkBuffers.push(data)
40-
}
41-
});
42-
const output = Buffer.concat(benchmarkBuffers).toString('utf8')
43-
return parse(output)
44-
}
45-
46-
const firstLineRe = /^Running '(.+)' \.\.\.$/
47-
const secondLineRe = /^done ([\d.]+) ms$/
37+
let benchmarkBuffers = [];
38+
await exec(getInput("benchmark"), [], {
39+
listeners: {
40+
stdout: (data) => benchmarkBuffers.push(data),
41+
},
42+
});
43+
const output = Buffer.concat(benchmarkBuffers).toString("utf8");
44+
return parse(output);
45+
};
46+
47+
const firstLineRe = /^Running '(.+)' \.\.\.$/;
48+
const secondLineRe = /^done ([\d.]+) ms$/;
4849

4950
function parse(benchmarkData) {
50-
const lines = benchmarkData.trim().split('\n')
51-
const benchmarks = Object.create(null)
52-
for (let i = 0; i < lines.length - 1; i += 2) {
53-
const [, name] = firstLineRe.exec(lines[i])
54-
const [, time] = secondLineRe.exec(lines[i + 1])
55-
benchmarks[name] = Math.round(parseFloat(time))
56-
}
57-
return benchmarks
51+
const lines = benchmarkData.trim().split("\n");
52+
const benchmarks = Object.create(null);
53+
for (let i = 0; i < lines.length - 1; i += 2) {
54+
const [, name] = firstLineRe.exec(lines[i]);
55+
const [, time] = secondLineRe.exec(lines[i + 1]);
56+
benchmarks[name] = Math.round(parseFloat(time));
57+
}
58+
return benchmarks;
5859
}
5960

6061
exports.averageBenchmarks = (benchmarks) => {
61-
const result = Object.create(null)
62-
for (const key of Object.keys(benchmarks[0])) {
63-
result[key] = benchmarks.reduce((acc, bench) => acc + bench[key], 0) / benchmarks.length
64-
}
65-
return result
66-
}
62+
const result = Object.create(null);
63+
for (const key of Object.keys(benchmarks[0])) {
64+
result[key] =
65+
benchmarks.reduce((acc, bench) => acc + bench[key], 0) /
66+
benchmarks.length;
67+
}
68+
return result;
69+
};
6770

6871
/**
6972
* @param {{[key: string]: number}} before
7073
* @param {{[key: string]: number}} after
7174
* @return {Diff[]}
7275
*/
7376
exports.toDiff = (before, after) => {
74-
const names = [...new Set([...Object.keys(before), ...Object.keys(after)])]
75-
return names.map(name => {
76-
const timeBefore = before[name] || 0
77-
const timeAfter = after[name] || 0
78-
const delta = timeAfter - timeBefore
79-
return { name, time: timeAfter, delta }
80-
})
81-
}
82-
77+
const names = [...new Set([...Object.keys(before), ...Object.keys(after)])];
78+
return names.map((name) => {
79+
const timeBefore = before[name] || 0;
80+
const timeAfter = after[name] || 0;
81+
const delta = timeAfter - timeBefore;
82+
return { name, time: timeAfter, delta };
83+
});
84+
};
8385

8486
/**
8587
* @param {number} delta
8688
* @param {number} difference
8789
*/
8890
function getDeltaText(delta, difference) {
89-
let deltaText = (delta > 0 ? '+' : '') + delta.toLocaleString('en-US') + 'ms';
90-
if (delta && Math.abs(delta) > 1) {
91-
deltaText += ` (${Math.abs(difference)}%)`;
92-
}
93-
return deltaText;
91+
let deltaText =
92+
(delta > 0 ? "+" : "") + delta.toLocaleString("en-US") + "ms";
93+
if (delta && Math.abs(delta) > 1) {
94+
deltaText += ` (${Math.abs(difference)}%)`;
95+
}
96+
return deltaText;
9497
}
9598

9699
/**
97100
* @param {number} difference
98101
*/
99102
function iconForDifference(difference) {
100-
let icon = '';
101-
if (difference >= 50) icon = '🆘';
102-
else if (difference >= 20) icon = '🚨';
103-
else if (difference >= 10) icon = '⚠️';
104-
else if (difference >= 5) icon = '🔍';
105-
else if (difference <= -50) icon = '🏆';
106-
else if (difference <= -20) icon = '🎉';
107-
else if (difference <= -10) icon = '👏';
108-
else if (difference <= -5) icon = '✅';
109-
return icon;
103+
let icon = "";
104+
if (difference >= 50) icon = "🆘";
105+
else if (difference >= 20) icon = "🚨";
106+
else if (difference >= 10) icon = "⚠️";
107+
else if (difference >= 5) icon = "🔍";
108+
else if (difference <= -50) icon = "🏆";
109+
else if (difference <= -20) icon = "🎉";
110+
else if (difference <= -10) icon = "👏";
111+
else if (difference <= -5) icon = "✅";
112+
return icon;
110113
}
111114

112115
/**
113116
* Create a Markdown table from text rows
114117
* @param {string[]} rows
115118
*/
116119
function markdownTable(rows) {
117-
if (rows.length == 0) {
118-
return '';
119-
}
120-
121-
// Skip all empty columns
122-
while (rows.every(columns => !columns[columns.length - 1])) {
123-
for (const columns of rows) {
124-
columns.pop();
125-
}
126-
}
127-
128-
const [firstRow] = rows;
129-
const columnLength = firstRow.length;
130-
if (columnLength === 0) {
131-
return '';
132-
}
133-
134-
return [
135-
// Header
136-
['Test name', 'Duration', 'Change', ''].slice(0, columnLength),
137-
// Align
138-
[':---', ':---:', ':---:', ':---:'].slice(0, columnLength),
139-
// Body
140-
...rows
141-
].map(columns => `| ${columns.join(' | ')} |`).join('\n');
120+
if (rows.length == 0) {
121+
return "";
122+
}
123+
124+
// Skip all empty columns
125+
while (rows.every((columns) => !columns[columns.length - 1])) {
126+
for (const columns of rows) {
127+
columns.pop();
128+
}
129+
}
130+
131+
const [firstRow] = rows;
132+
const columnLength = firstRow.length;
133+
if (columnLength === 0) {
134+
return "";
135+
}
136+
137+
return [
138+
// Header
139+
["Test name", "Duration", "Change", ""].slice(0, columnLength),
140+
// Align
141+
[":---", ":---:", ":---:", ":---:"].slice(0, columnLength),
142+
// Body
143+
...rows,
144+
]
145+
.map((columns) => `| ${columns.join(" | ")} |`)
146+
.join("\n");
142147
}
143148

144149
/**
@@ -157,55 +162,60 @@ function markdownTable(rows) {
157162
* @param {boolean} [options.omitUnchanged]
158163
* @param {number} [options.minimumChangeThreshold]
159164
*/
160-
exports.diffTable = (tests, { showTotal, collapseUnchanged, omitUnchanged, minimumChangeThreshold }) => {
161-
let changedRows = [];
162-
let unChangedRows = [];
163-
164-
let totalTime = 0;
165-
let totalDelta = 0;
166-
for (const file of tests) {
167-
const { name, time, delta } = file;
168-
totalTime += time;
169-
totalDelta += delta;
170-
171-
const difference = ((delta / time) * 100) | 0;
172-
const isUnchanged = Math.abs(difference) < minimumChangeThreshold;
173-
174-
if (isUnchanged && omitUnchanged) continue;
175-
176-
const columns = [
177-
name,
178-
time.toLocaleString('en-US') + 'ms',
179-
getDeltaText(delta, difference),
180-
iconForDifference(difference)
181-
];
182-
if (isUnchanged && collapseUnchanged) {
183-
unChangedRows.push(columns);
184-
} else {
185-
changedRows.push(columns);
186-
}
187-
}
188-
189-
let out = markdownTable(changedRows);
190-
191-
if (unChangedRows.length !== 0) {
192-
const outUnchanged = markdownTable(unChangedRows);
193-
out += `\n\n<details><summary>ℹ️ <strong>View Unchanged</strong></summary>\n\n${outUnchanged}\n\n</details>\n\n`;
194-
}
195-
196-
if (showTotal) {
197-
const totalDifference = ((totalDelta / totalTime) * 100) | 0;
198-
let totalDeltaText = getDeltaText(totalDelta, totalDifference);
199-
let totalIcon = iconForDifference(totalDifference);
200-
out = `**Total Time:** ${totalTime.toLocaleString('en-US')}ms\n\n${out}`;
201-
out = `**Time Change:** ${totalDeltaText} ${totalIcon}\n\n${out}`;
202-
}
203-
204-
return out;
205-
}
165+
exports.diffTable = (
166+
tests,
167+
{ showTotal, collapseUnchanged, omitUnchanged, minimumChangeThreshold }
168+
) => {
169+
let changedRows = [];
170+
let unChangedRows = [];
171+
172+
let totalTime = 0;
173+
let totalDelta = 0;
174+
for (const file of tests) {
175+
const { name, time, delta } = file;
176+
totalTime += time;
177+
totalDelta += delta;
178+
179+
const difference = ((delta / time) * 100) | 0;
180+
const isUnchanged = Math.abs(difference) < minimumChangeThreshold;
181+
182+
if (isUnchanged && omitUnchanged) continue;
183+
184+
const columns = [
185+
name,
186+
time.toLocaleString("en-US") + "ms",
187+
getDeltaText(delta, difference),
188+
iconForDifference(difference),
189+
];
190+
if (isUnchanged && collapseUnchanged) {
191+
unChangedRows.push(columns);
192+
} else {
193+
changedRows.push(columns);
194+
}
195+
}
196+
197+
let out = markdownTable(changedRows);
198+
199+
if (unChangedRows.length !== 0) {
200+
const outUnchanged = markdownTable(unChangedRows);
201+
out += `\n\n<details><summary>ℹ️ <strong>View Unchanged</strong></summary>\n\n${outUnchanged}\n\n</details>\n\n`;
202+
}
203+
204+
if (showTotal) {
205+
const totalDifference = ((totalDelta / totalTime) * 100) | 0;
206+
let totalDeltaText = getDeltaText(totalDelta, totalDifference);
207+
let totalIcon = iconForDifference(totalDifference);
208+
out = `**Total Time:** ${totalTime.toLocaleString(
209+
"en-US"
210+
)}ms\n\n${out}`;
211+
out = `**Time Change:** ${totalDeltaText} ${totalIcon}\n\n${out}`;
212+
}
213+
214+
return out;
215+
};
206216

207217
/**
208218
* Convert a string "true"/"yes"/"1" argument value to a boolean
209219
* @param {string} v
210220
*/
211-
exports.toBool = v => /^(1|true|yes)$/.test(v);
221+
exports.toBool = (v) => /^(1|true|yes)$/.test(v);

0 commit comments

Comments
 (0)
Please sign in to comment.