Skip to content

Commit 75afb6a

Browse files
committed
Improve: Add performance / stress-test script
- Add bulk file test script to gather some simple stats on speed - Fix some minor type issues - Add tsc check script entry (`--noEmit`)
1 parent cbc1f4e commit 75afb6a

File tree

3 files changed

+139
-1
lines changed

3 files changed

+139
-1
lines changed

__tests__/helpers.test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ test('replaceInObj', t => {
5050
}
5151
}
5252
};
53+
/** @param {string | number} input */
5354
const replacer = function(input) {
5455
if (typeof (input) === 'string') {
5556
return input.toLowerCase();

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
"test": "xo && nyc ava",
2828
"lint": "xo",
2929
"test-nolint": "nyc ava",
30-
"build": "rm -rf dist && tsc"
30+
"build": "rm -rf dist && tsc",
31+
"tsc-check": "tsc --noEmit",
32+
"benchmark": "node scripts/perf-stress-test.js"
3133
},
3234
"files": [
3335
"dist/"

scripts/perf-stress-test.js

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// @ts-check
2+
const {makeTempDir, iDebugLog} = require('../tst-helpers');
3+
const fse = require('fs-extra');
4+
const {posixNormalize} = require('../src/helpers');
5+
const childProc = require('child_process');
6+
const main = require('../src');
7+
8+
const ROOT_FILE_COUNT = 120;
9+
// How many top-level subdirs to create
10+
const SUBDIR_ROOT_COUNT = 4;
11+
// Contents of top-level subdirs
12+
const SUBDIR_LEVELS = 3;
13+
const SUBDIR_FILE_COUNT = 20;
14+
const FILE_CONTENTS = `TEST FILE -- ⏱ --`;
15+
16+
/** @type {string} */
17+
let tempDirPath;
18+
19+
const perfInfo = {
20+
testMeta: {
21+
timeToCreateFilesMs: 0,
22+
totalFileCount: 0
23+
},
24+
results: {
25+
totalExecutionTimeMs: 0,
26+
totalExecutionTimeSec: 0,
27+
filesPerSec: 0
28+
}
29+
};
30+
31+
const timer = {
32+
fileCreation: {
33+
start: 0,
34+
stop: 0
35+
},
36+
program: {
37+
start: 0,
38+
stop: 0
39+
}
40+
};
41+
42+
const getRandExtension = () => {
43+
const extensions = ['txt', 'md', 'html'];
44+
return extensions[Math.floor(Math.random() * extensions.length)];
45+
};
46+
47+
const folderNames = ['alpha', 'bravo', 'charlie', 'delta'];
48+
const getRandFolderName = () => {
49+
return folderNames[Math.floor(Math.random() * folderNames.length)];
50+
};
51+
52+
/**
53+
*
54+
* @param {string} folderPath
55+
* @param {number} num
56+
*/
57+
const getTestFilePath = (folderPath, num) => {
58+
const slash = folderPath.endsWith('/') ? '' : '/';
59+
return `${folderPath}${slash}t-${num}.${getRandExtension()}`;
60+
};
61+
62+
const stressTest = async () => {
63+
const filePaths = [];
64+
timer.fileCreation.start = new Date().getTime();
65+
tempDirPath = posixNormalize(await makeTempDir());
66+
// Create root files
67+
for (let x = 0; x < ROOT_FILE_COUNT; x++) {
68+
filePaths.push(getTestFilePath(tempDirPath, x));
69+
}
70+
// Create subdir files
71+
for (let x = 0; x < SUBDIR_ROOT_COUNT && x < folderNames.length; x++) {
72+
const baseFolderName = folderNames[x];
73+
for (let s = 1; s < SUBDIR_LEVELS; s++) {
74+
const subDirPath = `${tempDirPath}/${baseFolderName}/${new Array(s).fill(0).map(getRandFolderName).join('/')}`;
75+
for (let f = 0; f < SUBDIR_FILE_COUNT; f++) {
76+
filePaths.push(getTestFilePath(subDirPath, f));
77+
}
78+
}
79+
}
80+
81+
// Wait for all files to be created
82+
await Promise.all(filePaths.map(async (p) => {
83+
await fse.ensureFile(p);
84+
await fse.writeFile(p, FILE_CONTENTS);
85+
}));
86+
timer.fileCreation.stop = new Date().getTime();
87+
const totalFileCount = filePaths.length;
88+
perfInfo.testMeta = {
89+
timeToCreateFilesMs: timer.fileCreation.stop - timer.fileCreation.start,
90+
totalFileCount
91+
};
92+
93+
// Git init
94+
childProc.execSync('git init', {
95+
cwd: tempDirPath
96+
});
97+
childProc.execSync('git add . && git commit -m "Adding files"', {
98+
cwd: tempDirPath
99+
});
100+
101+
// Run program
102+
timer.program.start = new Date().getTime();
103+
/** @type {import('../src/types').InputOptions} */
104+
const programOptions = {
105+
projectRootPath: tempDirPath,
106+
outputToFile: true
107+
};
108+
const result = await main.getStamps(programOptions);
109+
timer.program.stop = new Date().getTime();
110+
111+
// Gather and return results
112+
console.assert(Object.keys(result).length === totalFileCount, 'Something went wrong with file generation, or program; # of files with date info does not match # supposed to be generated');
113+
const totalExecutionTimeMs = timer.program.stop - timer.program.start;
114+
const totalExecutionTimeSec = totalExecutionTimeMs / 1000;
115+
perfInfo.results = {
116+
totalExecutionTimeMs,
117+
totalExecutionTimeSec,
118+
filesPerSec: totalFileCount / totalExecutionTimeSec
119+
};
120+
return perfInfo;
121+
};
122+
123+
const teardown = async () => {
124+
await fse.remove(tempDirPath);
125+
};
126+
127+
const run = async() => {
128+
const results = await stressTest();
129+
iDebugLog(results);
130+
await teardown();
131+
};
132+
133+
run().then(() => {
134+
console.log(`Done!`);
135+
});

0 commit comments

Comments
 (0)