From 06d4775178af40264d0dfe476ee11815235fc52e Mon Sep 17 00:00:00 2001 From: Christina Ying Wang Date: Fri, 29 Sep 2023 12:11:33 -0700 Subject: [PATCH] Use native structuredClone instead of _.cloneDeep Memory tests have shown performance improvements to using the native method. Change-type: patch Signed-off-by: Christina Ying Wang --- package.json | 4 ++-- src/api-binder/index.ts | 2 +- src/compose/application-manager.ts | 2 +- src/compose/network.ts | 4 ++-- src/compose/utils.ts | 2 +- src/device-config.ts | 2 +- src/device-state/target-state.ts | 4 ++-- src/event-tracker.ts | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 6e880e3e..3b05f0f8 100644 --- a/package.json +++ b/package.json @@ -40,8 +40,8 @@ "systeminformation": "^5.6.10" }, "engines": { - "node": ">=16.17.0", - "npm": ">=8.15.0" + "node": ">=18.18.0", + "npm": ">=9.8.1" }, "devDependencies": { "@balena/contrato": "^0.6.0", diff --git a/src/api-binder/index.ts b/src/api-binder/index.ts index 51d64622..7fd7401e 100644 --- a/src/api-binder/index.ts +++ b/src/api-binder/index.ts @@ -528,7 +528,7 @@ export const initialized = _.once(async () => { } const baseUrl = url.resolve(apiEndpoint, '/v6/'); - const passthrough = _.cloneDeep(await request.getRequestOptions()); + const passthrough = structuredClone(await request.getRequestOptions()); passthrough.headers = passthrough.headers != null ? passthrough.headers : {}; passthrough.headers.Authorization = `Bearer ${currentApiKey}`; balenaApi = new PinejsClientRequest({ diff --git a/src/compose/application-manager.ts b/src/compose/application-manager.ts index 94b7d520..051d65bb 100644 --- a/src/compose/application-manager.ts +++ b/src/compose/application-manager.ts @@ -546,7 +546,7 @@ export async function setTarget( // filter those out and add the target state to the database const contractViolators: { [appName: string]: string[] } = {}; const fulfilledContracts = validateTargetContracts(apps); - const filteredApps = _.cloneDeep(apps); + const filteredApps = structuredClone(apps); _.each( fulfilledContracts, ( diff --git a/src/compose/network.ts b/src/compose/network.ts index 81ff7dcf..3e0705ef 100644 --- a/src/compose/network.ts +++ b/src/compose/network.ts @@ -261,7 +261,7 @@ export class Network { // default or generated values) let configToCompare = this.config; if (network.config.ipam.config.length === 0) { - configToCompare = _.cloneDeep(this.config); + configToCompare = structuredClone(this.config); configToCompare.ipam.config = []; } @@ -270,7 +270,7 @@ export class Network { // Any ipam config will be included in the network, but not applied // in the host's networking layer. if (network.config.configOnly) { - configToCompare = _.cloneDeep(this.config); + configToCompare = structuredClone(this.config); configToCompare.driver = network.config.driver; } diff --git a/src/compose/utils.ts b/src/compose/utils.ts index 1b5d89f4..8e924f81 100644 --- a/src/compose/utils.ts +++ b/src/compose/utils.ts @@ -30,7 +30,7 @@ export function camelCaseConfig( // Networks can either be an object or array, but given _.isObject // returns true for an array, we check the other way if (!_.isArray(config.networks)) { - const networksTmp = _.cloneDeep(config.networks); + const networksTmp = structuredClone(config.networks); _.each(networksTmp, (v, k) => { config.networks[k] = _.mapKeys(v, (_v, key) => _.camelCase(key)); }); diff --git a/src/device-config.ts b/src/device-config.ts index 50ddd6be..e72aaaf3 100644 --- a/src/device-config.ts +++ b/src/device-config.ts @@ -389,7 +389,7 @@ export function bootConfigChangeRequired( const SPECIAL_CASE = 'configuration'; // ODMDATA Mode for TX2 devices if (!(SPECIAL_CASE in targetBootConfig)) { // Create a copy to modify - const targetCopy = _.cloneDeep(targetBootConfig); + const targetCopy = structuredClone(targetBootConfig); // Add current value to simulate if the value was set in the cloud on provision targetCopy[SPECIAL_CASE] = currentBootConfig[SPECIAL_CASE]; if (_.isEqual(targetCopy, currentBootConfig)) { diff --git a/src/device-state/target-state.ts b/src/device-state/target-state.ts index 8b75f635..66fa26bb 100644 --- a/src/device-state/target-state.ts +++ b/src/device-state/target-state.ts @@ -64,7 +64,7 @@ const emitTargetState = ( // CachedResponse has not been emitted before so emit as an update emitter.emit( 'target-state-update', - _.cloneDeep(cachedResponse.body), + structuredClone(cachedResponse.body), force, isFromApi, ); @@ -201,7 +201,7 @@ const poll = async ( */ export const get = async (): Promise => { await update(); - return _.cloneDeep(cache.body); + return structuredClone(cache.body); }; /** diff --git a/src/event-tracker.ts b/src/event-tracker.ts index 79174bf5..bd2224e3 100644 --- a/src/event-tracker.ts +++ b/src/event-tracker.ts @@ -24,7 +24,7 @@ export async function track( properties = { error: properties }; } - properties = _.cloneDeep(properties); + properties = structuredClone(properties); if (properties.error instanceof Error) { // Format the error for printing, to avoid display as { } properties.error = {