From b299907a83cce822a9b6ace1328e9b15fd103f95 Mon Sep 17 00:00:00 2001 From: Sameena Shaffeeullah Date: Wed, 16 Nov 2022 19:00:48 +0000 Subject: [PATCH 1/4] refactor: refactor constants --- .../performApplicationPerformanceTest.ts | 172 ++++++++++-------- .../performTransferManagerTest.ts | 82 ++++----- internal-tooling/performanceUtils.ts | 3 +- 3 files changed, 136 insertions(+), 121 deletions(-) diff --git a/internal-tooling/performApplicationPerformanceTest.ts b/internal-tooling/performApplicationPerformanceTest.ts index 7ff67e07f..a9dda8377 100644 --- a/internal-tooling/performApplicationPerformanceTest.ts +++ b/internal-tooling/performApplicationPerformanceTest.ts @@ -15,7 +15,7 @@ */ import yargs from 'yargs'; -import {promises as fsp} from 'fs'; +import {promises as fsp, rmSync} from 'fs'; import { Bucket, DownloadOptions, @@ -27,7 +27,12 @@ import {performance} from 'perf_hooks'; // eslint-disable-next-line node/no-unsupported-features/node-builtins import {parentPort} from 'worker_threads'; import { + BLOCK_SIZE_IN_BYTES, DEFAULT_PROJECT_ID, + DEFAULT_NUMBER_OF_OBJECTS, + DEFAULT_SMALL_FILE_SIZE_BYTES, + DEFAULT_LARGE_FILE_SIZE_BYTES, + NODE_DEFAULT_HIGHWATER_MARK_BYTES, generateRandomDirectoryStructure, getValidationType, performanceTestSetup, @@ -35,14 +40,8 @@ import { } from './performanceUtils'; import {TRANSFER_MANAGER_TEST_TYPES} from './performanceTest'; -const TEST_NAME_STRING = 'nodejs-perf-metrics'; -const DEFAULT_NUMBER_OF_WRITES = 1; -const DEFAULT_NUMBER_OF_READS = 3; +const TEST_NAME_STRING = 'nodejs-perf-metrics-application'; const DEFAULT_BUCKET_NAME = 'nodejs-perf-metrics-shaffeeullah'; -const DEFAULT_SMALL_FILE_SIZE_BYTES = 5120; -const DEFAULT_LARGE_FILE_SIZE_BYTES = 2.147e9; -const BLOCK_SIZE_IN_BYTES = 1024; -const NODE_DEFAULT_HIGHWATER_MARK_BYTES = 16384; let stg: Storage; let bucket: Bucket; @@ -55,6 +54,7 @@ const argv = yargs(process.argv.slice(2)) small: {type: 'number', default: DEFAULT_SMALL_FILE_SIZE_BYTES}, large: {type: 'number', default: DEFAULT_LARGE_FILE_SIZE_BYTES}, projectid: {type: 'string', default: DEFAULT_PROJECT_ID}, + numobjects: {type: 'number', default: DEFAULT_NUMBER_OF_OBJECTS} }) .parseSync(); @@ -63,23 +63,38 @@ const argv = yargs(process.argv.slice(2)) * to the parent thread. */ async function main() { - let results: TestResult[] = []; + let result: TestResult = { + op: '', + objectSize: 0, + appBufferSize: 0, + libBufferSize: 0, + crc32Enabled: false, + md5Enabled: false, + apiName: 'JSON', + elapsedTimeUs: 0, + cpuTimeUs: 0, + status: '[OK]', + }; + + console.log("SAMEENA") + console.log(argv.numobjects); + ({bucket} = await performanceTestSetup(argv.projectid, argv.bucket)); switch (argv.testtype) { case TRANSFER_MANAGER_TEST_TYPES.APPLICATION_UPLOAD_MULTIPLE_OBJECTS: - results = await performWriteTest(); + result = await performWriteTest(); break; case TRANSFER_MANAGER_TEST_TYPES.APPLICATION_DOWNLOAD_MULTIPLE_OBJECTS: - results = await performReadTest(); + result = await performReadTest(); break; // case TRANSFER_MANAGER_TEST_TYPES.APPLICATION_LARGE_FILE_DOWNLOAD: - // results = await performLargeReadTest(); + // result = await performLargeReadTest(); // break; default: break; } - parentPort?.postMessage(results); + parentPort?.postMessage(result); } async function uploadInParallel( @@ -112,79 +127,80 @@ async function downloadInParallel(bucket: Bucket, options: DownloadOptions) { /** * Performs an iteration of the Write multiple objects test. * - * @returns {Promise} Promise that resolves to an array of test results for the iteration. + * @returns {Promise} Promise that resolves to a test result of an iteration. */ -async function performWriteTest(): Promise { - const results: TestResult[] = []; - const directory = TEST_NAME_STRING; - const directories = generateRandomDirectoryStructure(10, directory); - - for (let j = 0; j < DEFAULT_NUMBER_OF_WRITES; j++) { - let start = 0; - let end = 0; - - const iterationResult: TestResult = { - op: 'WRITE', - objectSize: BLOCK_SIZE_IN_BYTES, //note this is wrong - appBufferSize: BLOCK_SIZE_IN_BYTES, - libBufferSize: NODE_DEFAULT_HIGHWATER_MARK_BYTES, - crc32Enabled: false, - md5Enabled: false, - apiName: 'JSON', - elapsedTimeUs: 0, - cpuTimeUs: -1, - status: '[OK]', - }; - - bucket = stg.bucket(argv.bucket, { - preconditionOpts: { - ifGenerationMatch: 0, - }, - }); - - await bucket.deleteFiles(); //cleanup anything old - start = performance.now(); - await uploadInParallel(bucket, directories.paths, {validation: checkType}); - end = performance.now(); - - iterationResult.elapsedTimeUs = Math.round((end - start) * 1000); - results.push(iterationResult); - } - return results; +async function performWriteTest(): Promise { + await bucket.deleteFiles(); //start clean + + const creationInfo = generateRandomDirectoryStructure( + argv.numobjects, + TEST_NAME_STRING, + argv.small, + argv.large + ); + + bucket = stg.bucket(argv.bucket, { + preconditionOpts: { + ifGenerationMatch: 0, + }, + }); + let start = performance.now(); + await uploadInParallel(bucket, creationInfo.paths, {validation: checkType}); + let end = performance.now(); + + await bucket.deleteFiles(); //cleanup files + + const result: TestResult = { + op: 'WRITE', + objectSize: creationInfo.totalSizeInBytes, + appBufferSize: BLOCK_SIZE_IN_BYTES, + libBufferSize: NODE_DEFAULT_HIGHWATER_MARK_BYTES, + crc32Enabled: checkType === 'crc32c', + md5Enabled: checkType === 'md5', + apiName: 'JSON', + elapsedTimeUs: Math.round((end - start) * 1000), + cpuTimeUs: -1, + status: '[OK]', + }; + return result; } /** * Performs an iteration of the read multiple objects test. * - * @returns {Promise} Promise that resolves to an array of test results for the iteration. + * @returns {Promise} Promise that resolves to an array of test results for the iteration. */ -async function performReadTest(): Promise { - const results: TestResult[] = []; +async function performReadTest(): Promise { bucket = stg.bucket(argv.bucket); - for (let j = 0; j < DEFAULT_NUMBER_OF_READS; j++) { - let start = 0; - let end = 0; - const iterationResult: TestResult = { - op: `READ[${j}]`, - objectSize: 0, //this is wrong - appBufferSize: BLOCK_SIZE_IN_BYTES, - libBufferSize: NODE_DEFAULT_HIGHWATER_MARK_BYTES, - crc32Enabled: false, - md5Enabled: false, - apiName: 'JSON', - elapsedTimeUs: 0, - cpuTimeUs: -1, - status: '[OK]', - }; - - start = performance.now(); - await downloadInParallel(bucket, {validation: checkType}); - end = performance.now(); - - iterationResult.elapsedTimeUs = Math.round((end - start) * 1000); - results.push(iterationResult); - } - return results; + await bucket.deleteFiles(); // start clean + const creationInfo = generateRandomDirectoryStructure( + argv.numobjects, + TEST_NAME_STRING, + argv.small, + argv.large + ); + await uploadInParallel(bucket, creationInfo.paths, {validation: checkType}); + + let start = performance.now(); + await downloadInParallel(bucket, {validation: checkType}); + let end = performance.now(); + + const result: TestResult = { + op: 'READ', + objectSize: creationInfo.totalSizeInBytes, + appBufferSize: BLOCK_SIZE_IN_BYTES, + libBufferSize: NODE_DEFAULT_HIGHWATER_MARK_BYTES, + crc32Enabled: checkType === 'crc32c', + md5Enabled: checkType === 'md5', + apiName: 'JSON', + elapsedTimeUs: Math.round((end - start) * 1000), + cpuTimeUs: -1, + status: '[OK]', + }; + + rmSync(TEST_NAME_STRING, {recursive: true, force: true}); + await bucket.deleteFiles(); //cleanup + return result; } main(); diff --git a/internal-tooling/performTransferManagerTest.ts b/internal-tooling/performTransferManagerTest.ts index 80e685c5f..5d31515c8 100644 --- a/internal-tooling/performTransferManagerTest.ts +++ b/internal-tooling/performTransferManagerTest.ts @@ -30,6 +30,7 @@ import { generateRandomFileName, getValidationType, NODE_DEFAULT_HIGHWATER_MARK_BYTES, + DEFAULT_NUMBER_OF_OBJECTS, performanceTestSetup, TestResult, } from './performanceUtils'; @@ -39,7 +40,6 @@ import {rmSync} from 'fs'; const TEST_NAME_STRING = 'tm-perf-metrics'; const DEFAULT_BUCKET_NAME = 'nodejs-transfer-manager-perf-metrics'; const DEFAULT_NUMBER_OF_PROMISES = 2; -const DEFAULT_NUMBER_OF_OBJECTS = 1000; const DEFAULT_CHUNK_SIZE_BYTES = 16 * 1024 * 1024; const DIRECTORY_PROBABILITY = 0.1; @@ -120,18 +120,6 @@ async function performTestCleanup() { * @returns {Promise} A promise that resolves containing information about the test results. */ async function performUploadMultipleObjectsTest(): Promise { - const result: TestResult = { - op: 'WRITE', - objectSize: 0, - appBufferSize: BLOCK_SIZE_IN_BYTES, - libBufferSize: NODE_DEFAULT_HIGHWATER_MARK_BYTES, - crc32Enabled: checkType === 'crc32c', - md5Enabled: checkType === 'md5', - apiName: 'JSON', - elapsedTimeUs: 0, - cpuTimeUs: -1, - status: '[OK]', - }; const creationInfo = generateRandomDirectoryStructure( argv.numobjects, TEST_NAME_STRING, @@ -139,7 +127,7 @@ async function performUploadMultipleObjectsTest(): Promise { argv.large, DIRECTORY_PROBABILITY ); - result.objectSize = creationInfo.totalSizeInBytes; + const start = performance.now(); await transferManager.uploadMulti(creationInfo.paths, { concurrencyLimit: argv.numpromises, @@ -149,31 +137,30 @@ async function performUploadMultipleObjectsTest(): Promise { }); const end = performance.now(); - result.elapsedTimeUs = Math.round((end - start) * 1000); rmSync(TEST_NAME_STRING, {recursive: true, force: true}); - return result; -} - -/** - * Performs a test where multiple objects are downloaded in parallel from a bucket. - * - * @returns {Promise} A promise that resolves containing information about the test results. - */ -async function performDownloadMultipleObjectsTest(): Promise { const result: TestResult = { - op: 'READ', - objectSize: 0, + op: 'WRITE', + objectSize: creationInfo.totalSizeInBytes, appBufferSize: BLOCK_SIZE_IN_BYTES, libBufferSize: NODE_DEFAULT_HIGHWATER_MARK_BYTES, crc32Enabled: checkType === 'crc32c', md5Enabled: checkType === 'md5', apiName: 'JSON', - elapsedTimeUs: 0, + elapsedTimeUs: Math.round((end - start) * 1000), cpuTimeUs: -1, status: '[OK]', }; + return result; +} + +/** + * Performs a test where multiple objects are downloaded in parallel from a bucket. + * + * @returns {Promise} A promise that resolves containing information about the test results. + */ +async function performDownloadMultipleObjectsTest(): Promise { const creationInfo = generateRandomDirectoryStructure( argv.numobjects, TEST_NAME_STRING, @@ -181,7 +168,7 @@ async function performDownloadMultipleObjectsTest(): Promise { argv.large, DIRECTORY_PROBABILITY ); - result.objectSize = creationInfo.totalSizeInBytes; + await transferManager.uploadMulti(creationInfo.paths, { concurrencyLimit: argv.numpromises, passthroughOptions: { @@ -198,9 +185,20 @@ async function performDownloadMultipleObjectsTest(): Promise { }); const end = performance.now(); - result.elapsedTimeUs = Math.round((end - start) * 1000); rmSync(TEST_NAME_STRING, {recursive: true, force: true}); + const result: TestResult = { + op: 'READ', + objectSize: creationInfo.totalSizeInBytes, + appBufferSize: BLOCK_SIZE_IN_BYTES, + libBufferSize: NODE_DEFAULT_HIGHWATER_MARK_BYTES, + crc32Enabled: checkType === 'crc32c', + md5Enabled: checkType === 'md5', + apiName: 'JSON', + elapsedTimeUs: Math.round((end - start) * 1000), + cpuTimeUs: -1, + status: '[OK]', + }; return result; } @@ -217,18 +215,6 @@ async function performDownloadLargeFileTest(): Promise { argv.large, __dirname ); - const result: TestResult = { - op: 'READ', - objectSize: sizeInBytes, - appBufferSize: BLOCK_SIZE_IN_BYTES, - libBufferSize: NODE_DEFAULT_HIGHWATER_MARK_BYTES, - crc32Enabled: false, - md5Enabled: false, - apiName: 'JSON', - elapsedTimeUs: 0, - cpuTimeUs: -1, - status: '[OK]', - }; const file = bucket.file(`${fileName}`); await bucket.upload(`${__dirname}/${fileName}`); @@ -241,9 +227,21 @@ async function performDownloadLargeFileTest(): Promise { }); const end = performance.now(); - result.elapsedTimeUs = Math.round((end - start) * 1000); cleanupFile(fileName); + const result: TestResult = { + op: 'READ', + objectSize: sizeInBytes, + appBufferSize: BLOCK_SIZE_IN_BYTES, + libBufferSize: NODE_DEFAULT_HIGHWATER_MARK_BYTES, + crc32Enabled: false, + md5Enabled: false, + apiName: 'JSON', + elapsedTimeUs: Math.round((end - start) * 1000), + cpuTimeUs: -1, + status: '[OK]', + }; + return result; } diff --git a/internal-tooling/performanceUtils.ts b/internal-tooling/performanceUtils.ts index 2109ccc55..df8f69b08 100644 --- a/internal-tooling/performanceUtils.ts +++ b/internal-tooling/performanceUtils.ts @@ -23,8 +23,9 @@ export const BLOCK_SIZE_IN_BYTES = 1024; export const DEFAULT_SMALL_FILE_SIZE_BYTES = 5120; export const DEFAULT_LARGE_FILE_SIZE_BYTES = 2.147e9; export const NODE_DEFAULT_HIGHWATER_MARK_BYTES = 16384; -export const DEFAULT_DIRECTORY_PROBABILITY = 0.5; +export const DEFAULT_DIRECTORY_PROBABILITY = 0.1; export const DEFAULT_PROJECT_ID = 'GCS_NODE_PERFORMANCE_METRICS'; +export const DEFAULT_NUMBER_OF_OBJECTS = 1000; export interface TestResult { op: string; From fabbd48c90b2d33f95dae7d487b2daae6af611d8 Mon Sep 17 00:00:00 2001 From: Sameena Shaffeeullah Date: Wed, 16 Nov 2022 19:18:57 +0000 Subject: [PATCH 2/4] bug fixes --- .../performApplicationPerformanceTest.ts | 72 +------------------ 1 file changed, 3 insertions(+), 69 deletions(-) diff --git a/internal-tooling/performApplicationPerformanceTest.ts b/internal-tooling/performApplicationPerformanceTest.ts index a9dda8377..7adf1f0cb 100644 --- a/internal-tooling/performApplicationPerformanceTest.ts +++ b/internal-tooling/performApplicationPerformanceTest.ts @@ -54,7 +54,7 @@ const argv = yargs(process.argv.slice(2)) small: {type: 'number', default: DEFAULT_SMALL_FILE_SIZE_BYTES}, large: {type: 'number', default: DEFAULT_LARGE_FILE_SIZE_BYTES}, projectid: {type: 'string', default: DEFAULT_PROJECT_ID}, - numobjects: {type: 'number', default: DEFAULT_NUMBER_OF_OBJECTS} + numobjects: {type: 'number', default: DEFAULT_NUMBER_OF_OBJECTS}, }) .parseSync(); @@ -76,9 +76,6 @@ async function main() { status: '[OK]', }; - console.log("SAMEENA") - console.log(argv.numobjects); - ({bucket} = await performanceTestSetup(argv.projectid, argv.bucket)); switch (argv.testtype) { @@ -139,68 +136,5 @@ async function performWriteTest(): Promise { argv.large ); - bucket = stg.bucket(argv.bucket, { - preconditionOpts: { - ifGenerationMatch: 0, - }, - }); - let start = performance.now(); - await uploadInParallel(bucket, creationInfo.paths, {validation: checkType}); - let end = performance.now(); - - await bucket.deleteFiles(); //cleanup files - - const result: TestResult = { - op: 'WRITE', - objectSize: creationInfo.totalSizeInBytes, - appBufferSize: BLOCK_SIZE_IN_BYTES, - libBufferSize: NODE_DEFAULT_HIGHWATER_MARK_BYTES, - crc32Enabled: checkType === 'crc32c', - md5Enabled: checkType === 'md5', - apiName: 'JSON', - elapsedTimeUs: Math.round((end - start) * 1000), - cpuTimeUs: -1, - status: '[OK]', - }; - return result; -} - -/** - * Performs an iteration of the read multiple objects test. - * - * @returns {Promise} Promise that resolves to an array of test results for the iteration. - */ -async function performReadTest(): Promise { - bucket = stg.bucket(argv.bucket); - await bucket.deleteFiles(); // start clean - const creationInfo = generateRandomDirectoryStructure( - argv.numobjects, - TEST_NAME_STRING, - argv.small, - argv.large - ); - await uploadInParallel(bucket, creationInfo.paths, {validation: checkType}); - - let start = performance.now(); - await downloadInParallel(bucket, {validation: checkType}); - let end = performance.now(); - - const result: TestResult = { - op: 'READ', - objectSize: creationInfo.totalSizeInBytes, - appBufferSize: BLOCK_SIZE_IN_BYTES, - libBufferSize: NODE_DEFAULT_HIGHWATER_MARK_BYTES, - crc32Enabled: checkType === 'crc32c', - md5Enabled: checkType === 'md5', - apiName: 'JSON', - elapsedTimeUs: Math.round((end - start) * 1000), - cpuTimeUs: -1, - status: '[OK]', - }; - - rmSync(TEST_NAME_STRING, {recursive: true, force: true}); - await bucket.deleteFiles(); //cleanup - return result; -} - -main(); + const start = performance.now(); + await uploadInParallel(bucket, creationInfo.paths, {validatio \ No newline at end of file From 6e87dfbfc813dd925baf05f54c0ab3e368ab4198 Mon Sep 17 00:00:00 2001 From: Sameena Shaffeeullah Date: Wed, 16 Nov 2022 19:20:08 +0000 Subject: [PATCH 3/4] bug fixes --- .../performApplicationPerformanceTest.ts | 61 ++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/internal-tooling/performApplicationPerformanceTest.ts b/internal-tooling/performApplicationPerformanceTest.ts index 7adf1f0cb..a42790dd0 100644 --- a/internal-tooling/performApplicationPerformanceTest.ts +++ b/internal-tooling/performApplicationPerformanceTest.ts @@ -137,4 +137,63 @@ async function performWriteTest(): Promise { ); const start = performance.now(); - await uploadInParallel(bucket, creationInfo.paths, {validatio \ No newline at end of file + await uploadInParallel(bucket, creationInfo.paths, {validation: checkType}); + const end = performance.now(); + + await bucket.deleteFiles(); //cleanup files + rmSync(TEST_NAME_STRING, {recursive: true, force: true}); + + const result: TestResult = { + op: 'WRITE', + objectSize: creationInfo.totalSizeInBytes, + appBufferSize: BLOCK_SIZE_IN_BYTES, + libBufferSize: NODE_DEFAULT_HIGHWATER_MARK_BYTES, + crc32Enabled: checkType === 'crc32c', + md5Enabled: checkType === 'md5', + apiName: 'JSON', + elapsedTimeUs: Math.round((end - start) * 1000), + cpuTimeUs: -1, + status: '[OK]', + }; + return result; +} + +/** + * Performs an iteration of the read multiple objects test. + * + * @returns {Promise} Promise that resolves to an array of test results for the iteration. + */ +async function performReadTest(): Promise { + bucket = stg.bucket(argv.bucket); + await bucket.deleteFiles(); // start clean + const creationInfo = generateRandomDirectoryStructure( + argv.numobjects, + TEST_NAME_STRING, + argv.small, + argv.large + ); + await uploadInParallel(bucket, creationInfo.paths, {validation: checkType}); + + const start = performance.now(); + await downloadInParallel(bucket, {validation: checkType}); + const end = performance.now(); + + const result: TestResult = { + op: 'READ', + objectSize: creationInfo.totalSizeInBytes, + appBufferSize: BLOCK_SIZE_IN_BYTES, + libBufferSize: NODE_DEFAULT_HIGHWATER_MARK_BYTES, + crc32Enabled: checkType === 'crc32c', + md5Enabled: checkType === 'md5', + apiName: 'JSON', + elapsedTimeUs: Math.round((end - start) * 1000), + cpuTimeUs: -1, + status: '[OK]', + }; + + rmSync(TEST_NAME_STRING, {recursive: true, force: true}); + await bucket.deleteFiles(); //cleanup + return result; +} + +main(); From 0fb09ccc43a36e4c6f0d219f53c261bb55ecbb86 Mon Sep 17 00:00:00 2001 From: Sameena Shaffeeullah Date: Wed, 16 Nov 2022 19:22:40 +0000 Subject: [PATCH 4/4] bug fixes --- internal-tooling/performApplicationPerformanceTest.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/internal-tooling/performApplicationPerformanceTest.ts b/internal-tooling/performApplicationPerformanceTest.ts index a42790dd0..f5d8b615d 100644 --- a/internal-tooling/performApplicationPerformanceTest.ts +++ b/internal-tooling/performApplicationPerformanceTest.ts @@ -164,7 +164,6 @@ async function performWriteTest(): Promise { * @returns {Promise} Promise that resolves to an array of test results for the iteration. */ async function performReadTest(): Promise { - bucket = stg.bucket(argv.bucket); await bucket.deleteFiles(); // start clean const creationInfo = generateRandomDirectoryStructure( argv.numobjects,