Skip to content
This repository was archived by the owner on Mar 3, 2026. It is now read-only.

Commit 81f7850

Browse files
authored
Merge pull request #1 from ddelgrosso1/tm-performance-framework
feat: add directory generator to performance test framework
2 parents face55f + b4bc333 commit 81f7850

2 files changed

Lines changed: 121 additions & 47 deletions

File tree

internal-tooling/performPerformanceTest.ts

Lines changed: 11 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,25 @@
1515
*/
1616

1717
import yargs from 'yargs';
18-
import * as uuid from 'uuid';
19-
import {execSync} from 'child_process';
2018
import {unlinkSync} from 'fs';
2119
import {Storage} from '../src';
2220
import {performance} from 'perf_hooks';
2321
// eslint-disable-next-line node/no-unsupported-features/node-builtins
2422
import {parentPort} from 'worker_threads';
2523
import path = require('path');
24+
import {
25+
BLOCK_SIZE_IN_BYTES,
26+
DEFAULT_LARGE_FILE_SIZE_BYTES,
27+
DEFAULT_SMALL_FILE_SIZE_BYTES,
28+
generateRandomFile,
29+
generateRandomFileName,
30+
randomInteger,
31+
} from './performanceUtils';
2632

2733
const TEST_NAME_STRING = 'nodejs-perf-metrics';
2834
const DEFAULT_NUMBER_OF_WRITES = 1;
2935
const DEFAULT_NUMBER_OF_READS = 3;
3036
const DEFAULT_BUCKET_NAME = 'nodejs-perf-metrics';
31-
const DEFAULT_SMALL_FILE_SIZE_BYTES = 5120;
32-
const DEFAULT_LARGE_FILE_SIZE_BYTES = 2.147e9;
33-
const BLOCK_SIZE_IN_BYTES = 1024;
3437
const NODE_DEFAULT_HIGHWATER_MARK_BYTES = 16384;
3538

3639
export interface TestResult {
@@ -46,20 +49,6 @@ export interface TestResult {
4649
status: '[OK]';
4750
}
4851

49-
/**
50-
* Create a uniformly distributed random integer beween the inclusive min and max provided.
51-
*
52-
* @param {number} minInclusive lower bound (inclusive) of the range of random integer to return.
53-
* @param {number} maxInclusive upper bound (inclusive) of the range of random integer to return.
54-
* @returns {number} returns a random integer between minInclusive and maxInclusive
55-
*/
56-
const randomInteger = (minInclusive: number, maxInclusive: number) => {
57-
// Utilizing Math.random will generate uniformly distributed random numbers.
58-
return (
59-
Math.floor(Math.random() * (maxInclusive - minInclusive + 1)) + minInclusive
60-
);
61-
};
62-
6352
const argv = yargs(process.argv.slice(2))
6453
.options({
6554
bucket: {type: 'string', default: DEFAULT_BUCKET_NAME},
@@ -85,8 +74,8 @@ async function main() {
8574
*/
8675
async function performWriteReadTest(): Promise<TestResult[]> {
8776
const results: TestResult[] = [];
88-
const fileName = generateRandomFileName();
89-
const sizeInBytes = generateRandomFile(fileName);
77+
const fileName = generateRandomFileName(TEST_NAME_STRING);
78+
const sizeInBytes = generateRandomFile(fileName, argv.small, argv.large);
9079
const checkType = randomInteger(0, 2);
9180

9281
const stg = new Storage({
@@ -159,7 +148,7 @@ async function performWriteReadTest(): Promise<TestResult[]> {
159148
status: '[OK]',
160149
};
161150

162-
const destinationFileName = generateRandomFileName();
151+
const destinationFileName = generateRandomFileName(TEST_NAME_STRING);
163152
const destination = path.join(__dirname, destinationFileName);
164153
if (checkType === 0) {
165154
start = performance.now();
@@ -186,31 +175,6 @@ async function performWriteReadTest(): Promise<TestResult[]> {
186175
return results;
187176
}
188177

189-
/**
190-
* Creates a file with a size between the small (default 5120 bytes) and large (2.147e9 bytes) parameters.
191-
* The file is filled with random data.
192-
*
193-
* @param {string} fileName name of the file to generate.
194-
* @returns {number} the size of the file generated.
195-
*/
196-
function generateRandomFile(fileName: string) {
197-
const fileSizeBytes = randomInteger(argv.small, argv.large);
198-
const numberNeeded = Math.ceil(fileSizeBytes / BLOCK_SIZE_IN_BYTES);
199-
const cmd = `dd if=/dev/urandom of=${__dirname}/${fileName} bs=${BLOCK_SIZE_IN_BYTES} count=${numberNeeded} status=none iflag=fullblock`;
200-
execSync(cmd);
201-
202-
return fileSizeBytes;
203-
}
204-
205-
/**
206-
* Creates a random file name by appending a UUID to the TEST_NAME_STRING.
207-
*
208-
* @returns {string} random file name that was generated.
209-
*/
210-
function generateRandomFileName(): string {
211-
return `${TEST_NAME_STRING}.${uuid.v4()}`;
212-
}
213-
214178
/**
215179
* Deletes the file specified by the fileName parameter.
216180
*
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*!
2+
* Copyright 2022 Google LLC. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import {execSync} from 'child_process';
18+
import {mkdirSync} from 'fs';
19+
import path = require('path');
20+
import * as uuid from 'uuid';
21+
22+
export const BLOCK_SIZE_IN_BYTES = 1024;
23+
export const DEFAULT_SMALL_FILE_SIZE_BYTES = 5120;
24+
export const DEFAULT_LARGE_FILE_SIZE_BYTES = 2.147e9;
25+
26+
const CREATE_DIRECTORY = 1;
27+
28+
/**
29+
* Create a uniformly distributed random integer beween the inclusive min and max provided.
30+
*
31+
* @param {number} minInclusive lower bound (inclusive) of the range of random integer to return.
32+
* @param {number} maxInclusive upper bound (inclusive) of the range of random integer to return.
33+
* @returns {number} returns a random integer between minInclusive and maxInclusive
34+
*/
35+
export function randomInteger(minInclusive: number, maxInclusive: number) {
36+
// Utilizing Math.random will generate uniformly distributed random numbers.
37+
return (
38+
Math.floor(Math.random() * (maxInclusive - minInclusive + 1)) + minInclusive
39+
);
40+
}
41+
42+
/**
43+
* Creates a random file name by appending a UUID to the baseName.
44+
*
45+
* @param {string} baseName the base file name. A random uuid will be appended to this value.
46+
*
47+
* @returns {string} random file name that was generated.
48+
*/
49+
export function generateRandomFileName(baseName: string): string {
50+
return `${baseName}.${uuid.v4()}`;
51+
}
52+
53+
/**
54+
* Creates a file with a size between the small (default 5120 bytes) and large (2.147e9 bytes) parameters.
55+
* The file is filled with random data.
56+
*
57+
* @param {string} fileName name of the file to generate.
58+
* @param {number} fileSizeLowerBoundBytes minimum size of file to generate.
59+
* @param {number} fileSizeUpperBoundBytes maximum size of file to generate.
60+
* @param {string} currentDirectory the directory in which to generate the file.
61+
*
62+
* @returns {number} the size of the file generated.
63+
*/
64+
export function generateRandomFile(
65+
fileName: string,
66+
fileSizeLowerBoundBytes: number = DEFAULT_SMALL_FILE_SIZE_BYTES,
67+
fileSizeUpperBoundBytes: number = DEFAULT_LARGE_FILE_SIZE_BYTES,
68+
currentDirectory: string = __dirname
69+
) {
70+
const fileSizeBytes = randomInteger(
71+
fileSizeLowerBoundBytes,
72+
fileSizeUpperBoundBytes
73+
);
74+
const numberNeeded = Math.ceil(fileSizeBytes / BLOCK_SIZE_IN_BYTES);
75+
const cmd = `dd if=/dev/urandom of=${currentDirectory}/${fileName} bs=${BLOCK_SIZE_IN_BYTES} count=${numberNeeded} status=none iflag=fullblock`;
76+
execSync(cmd);
77+
78+
return fileSizeBytes;
79+
}
80+
81+
/**
82+
* Creates a random directory structure consisting of subdirectories and random files.
83+
*
84+
* @param {number} maxObjects the total number of subdirectories and files to generate.
85+
* @param {string} baseName the starting directory under which everything else is added. File names will have this value prepended.
86+
* @param {number} fileSizeLowerBoundBytes minimum size of file to generate.
87+
* @param {number} fileSizeUpperBoundBytes maximum size of file to generate.
88+
*/
89+
export function generateRandomDirectoryStructure(
90+
maxObjects: number,
91+
baseName: string,
92+
fileSizeLowerBoundBytes: number = DEFAULT_SMALL_FILE_SIZE_BYTES,
93+
fileSizeUpperBoundBytes: number = DEFAULT_LARGE_FILE_SIZE_BYTES
94+
) {
95+
let curPath = baseName;
96+
for (let i = 0; i < maxObjects; i++) {
97+
const dirOrFile = randomInteger(0, 1);
98+
if (dirOrFile === CREATE_DIRECTORY) {
99+
curPath = path.join(curPath, uuid.v4());
100+
mkdirSync(curPath, {recursive: true});
101+
} else {
102+
generateRandomFile(
103+
generateRandomFileName(baseName),
104+
fileSizeLowerBoundBytes,
105+
fileSizeUpperBoundBytes,
106+
curPath
107+
);
108+
}
109+
}
110+
}

0 commit comments

Comments
 (0)