From 0c58e0c202eafd13fc96ea40b045e8ce9f119e52 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Wed, 2 Jul 2025 19:44:11 +0200 Subject: [PATCH] perf: speed up mean and median computation MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- scripts/bundle.js | 1 + src/charging-station/ChargingStation.ts | 8 +++----- .../ocpp/1.6/OCPP16ServiceUtils.ts | 2 +- .../ocpp/2.0/OCPP20ServiceUtils.ts | 2 +- .../ocpp/OCPPIncomingRequestService.ts | 1 + .../ocpp/OCPPRequestService.ts | 1 + .../ocpp/OCPPResponseService.ts | 1 + .../ui-server/UIServerUtils.ts | 3 +-- src/utils/Configuration.ts | 2 +- src/utils/StatisticUtils.ts | 18 +++++++++++------- src/utils/Utils.ts | 6 +++--- tests/charging-station/Helpers.test.ts | 5 ++++- tests/utils/ErrorUtils.test.ts | 1 + 13 files changed, 30 insertions(+), 21 deletions(-) diff --git a/scripts/bundle.js b/scripts/bundle.js index a41b28ff..21080354 100644 --- a/scripts/bundle.js +++ b/scripts/bundle.js @@ -1,4 +1,5 @@ /* eslint-disable n/no-unpublished-import */ + import chalk from 'chalk' import { build } from 'esbuild' import { clean } from 'esbuild-plugin-clean' diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index fae2f7ed..de219234 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -228,7 +228,7 @@ export class ChargingStation extends EventEmitter { this.evses = new Map() this.requests = new Map() this.flushingMessageBuffer = false - this.messageQueue = new Array() + this.messageQueue = [] as string[] this.sharedLRUCache = SharedLRUCache.getInstance() this.idTagsCache = IdTagsCache.getInstance() this.chargingStationWorkerBroadcastChannel = new ChargingStationWorkerBroadcastChannel(this) @@ -1812,10 +1812,8 @@ export class ChargingStation extends EventEmitter { this, this.stationInfo.amperageLimitationOcppKey, // prettier-ignore - ( - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.stationInfo.maximumAmperage! * getAmperageLimitationUnitDivider(this.stationInfo) - ).toString() + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + (this.stationInfo.maximumAmperage! * getAmperageLimitationUnitDivider(this.stationInfo)).toString() ) } if (getConfigurationKey(this, StandardParametersKey.SupportedFeatureProfiles) == null) { diff --git a/src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts b/src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts index 010bd5b2..dba9fbf9 100644 --- a/src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts +++ b/src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts @@ -415,7 +415,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils { moduleName?: string, methodName?: string ): JSONSchemaType { - return super.parseJsonSchemaFile( + return OCPPServiceUtils.parseJsonSchemaFile( relativePath, OCPPVersion.VERSION_16, moduleName, diff --git a/src/charging-station/ocpp/2.0/OCPP20ServiceUtils.ts b/src/charging-station/ocpp/2.0/OCPP20ServiceUtils.ts index a02a3cea..82bd9f13 100644 --- a/src/charging-station/ocpp/2.0/OCPP20ServiceUtils.ts +++ b/src/charging-station/ocpp/2.0/OCPP20ServiceUtils.ts @@ -11,7 +11,7 @@ export class OCPP20ServiceUtils extends OCPPServiceUtils { moduleName?: string, methodName?: string ): JSONSchemaType { - return super.parseJsonSchemaFile( + return OCPPServiceUtils.parseJsonSchemaFile( relativePath, OCPPVersion.VERSION_201, moduleName, diff --git a/src/charging-station/ocpp/OCPPIncomingRequestService.ts b/src/charging-station/ocpp/OCPPIncomingRequestService.ts index ca2ea97a..15981f7e 100644 --- a/src/charging-station/ocpp/OCPPIncomingRequestService.ts +++ b/src/charging-station/ocpp/OCPPIncomingRequestService.ts @@ -14,6 +14,7 @@ import { OCPPError } from '../../exception/index.js' import { logger } from '../../utils/index.js' import { OCPPConstants } from './OCPPConstants.js' import { ajvErrorsToErrorType } from './OCPPServiceUtils.js' + type Ajv = _Ajv.default // eslint-disable-next-line @typescript-eslint/no-redeclare const Ajv = _Ajv.default diff --git a/src/charging-station/ocpp/OCPPRequestService.ts b/src/charging-station/ocpp/OCPPRequestService.ts index d847a6e8..439d656f 100644 --- a/src/charging-station/ocpp/OCPPRequestService.ts +++ b/src/charging-station/ocpp/OCPPRequestService.ts @@ -34,6 +34,7 @@ import { convertDateToISOString, getMessageTypeString, } from './OCPPServiceUtils.js' + type Ajv = _Ajv.default // eslint-disable-next-line @typescript-eslint/no-redeclare const Ajv = _Ajv.default diff --git a/src/charging-station/ocpp/OCPPResponseService.ts b/src/charging-station/ocpp/OCPPResponseService.ts index a4dfa834..42035849 100644 --- a/src/charging-station/ocpp/OCPPResponseService.ts +++ b/src/charging-station/ocpp/OCPPResponseService.ts @@ -12,6 +12,7 @@ import type { import { OCPPError } from '../../exception/index.js' import { Constants, logger } from '../../utils/index.js' import { ajvErrorsToErrorType } from './OCPPServiceUtils.js' + type Ajv = _Ajv.default // eslint-disable-next-line @typescript-eslint/no-redeclare const Ajv = _Ajv.default diff --git a/src/charging-station/ui-server/UIServerUtils.ts b/src/charging-station/ui-server/UIServerUtils.ts index 2e3ea7da..fd777440 100644 --- a/src/charging-station/ui-server/UIServerUtils.ts +++ b/src/charging-station/ui-server/UIServerUtils.ts @@ -60,6 +60,5 @@ export const getProtocolAndVersion = (protocolStr: string): [Protocol, ProtocolV } export const isLoopback = (address: string): boolean => { - // eslint-disable-next-line no-useless-escape - return /^localhost$|^127(?:\.\d+){0,2}\.\d+$|^(?:0*\:)*?:?0*1$/i.test(address) + return /^localhost$|^127(?:\.\d+){0,2}\.\d+$|^(?:0*:)*?:?0*1$/i.test(address) } diff --git a/src/utils/Configuration.ts b/src/utils/Configuration.ts index 9a3eec8a..a6482afe 100644 --- a/src/utils/Configuration.ts +++ b/src/utils/Configuration.ts @@ -591,7 +591,7 @@ export class Configuration { consoleWarnOnce( `${chalk.green(logPrefix())} ${chalk.yellow( // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - `${FileType.Configuration} ${this.configurationFile} file have changed, reload` + `${FileType.Configuration} ${Configuration.configurationFile} file have changed, reload` )}` ) delete Configuration.configurationData diff --git a/src/utils/StatisticUtils.ts b/src/utils/StatisticUtils.ts index 4b87465d..fc453236 100644 --- a/src/utils/StatisticUtils.ts +++ b/src/utils/StatisticUtils.ts @@ -2,19 +2,23 @@ export const mean = (dataSet: number[]): number => { if (Array.isArray(dataSet) && dataSet.length === 0) { return 0 } - return dataSet.reduce((accumulator, num) => accumulator + num, 0) / dataSet.length + if (Array.isArray(dataSet) && dataSet.length === 1) { + return dataSet[0] + } + return dataSet.reduce((accumulator, number) => accumulator + number, 0) / dataSet.length } export const median = (dataSet: number[]): number => { if (Array.isArray(dataSet) && dataSet.length === 0) { return 0 } - const sortedDataSet = dataSet.slice().sort((a, b) => a - b) - const length = sortedDataSet.length - if (length % 2 === 0) { - return (sortedDataSet[length / 2 - 1] + sortedDataSet[length / 2]) / 2 + if (Array.isArray(dataSet) && dataSet.length === 1) { + return dataSet[0] } - return sortedDataSet[Math.floor(length / 2)] + const sortedDataSet = dataSet.slice().sort((a, b) => a - b) + return ( + (sortedDataSet[(sortedDataSet.length - 1) >> 1] + sortedDataSet[sortedDataSet.length >> 1]) / 2 + ) } export const min = (...args: number[]): number => @@ -63,7 +67,7 @@ export const stdDeviation = (dataSet: number[], dataSetAverage: number = mean(da return 0 } return Math.sqrt( - dataSet.reduce((accumulator, num) => accumulator + Math.pow(num - dataSetAverage, 2), 0) / + dataSet.reduce((accumulator, num) => accumulator + (num - dataSetAverage) ** 2, 0) / (dataSet.length - 1) ) } diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts index efa0ec5f..c8a8b14d 100644 --- a/src/utils/Utils.ts +++ b/src/utils/Utils.ts @@ -47,7 +47,7 @@ export const has = (property: PropertyKey, object: null | object | undefined): b if (object == null) { return false } - return Object.prototype.hasOwnProperty.call(object, property) + return Object.hasOwn(object, property) } const type = (value: unknown): string => { @@ -255,7 +255,7 @@ export const getRandomFloat = (max = Number.MAX_VALUE, min = 0): number => { * @returns The rounded number. */ export const roundTo = (numberValue: number, scale: number): number => { - const roundPower = Math.pow(10, scale) + const roundPower = 10 ** scale return Math.round(numberValue * roundPower * (1 + Number.EPSILON)) / roundPower } @@ -334,7 +334,7 @@ export const insertAt = (str: string, subStr: string, pos: number): string => * @returns delay in milliseconds */ export const exponentialDelay = (retryNumber = 0, delayFactor = 100): number => { - const delay = Math.pow(2, retryNumber) * delayFactor + const delay = 2 ** retryNumber * delayFactor const randomSum = delay * 0.2 * secureRandom() // 0-20% of the delay return delay + randomSum } diff --git a/tests/charging-station/Helpers.test.ts b/tests/charging-station/Helpers.test.ts index cdba0181..93fa6495 100644 --- a/tests/charging-station/Helpers.test.ts +++ b/tests/charging-station/Helpers.test.ts @@ -1,4 +1,5 @@ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ + import { expect } from '@std/expect' import { describe, it } from 'node:test' @@ -202,7 +203,9 @@ await describe('Helpers test suite', async () => { t.mock.method(logger, 'warn') checkStationInfoConnectorStatus(1, {} as ConnectorStatus, 'log prefix |', 'test-template.json') expect(logger.warn.mock.calls.length).toBe(0) - const connectorStatus = { status: ConnectorStatusEnum.Available } as ConnectorStatus + const connectorStatus = { + status: ConnectorStatusEnum.Available, + } as ConnectorStatus checkStationInfoConnectorStatus(1, connectorStatus, 'log prefix |', 'test-template.json') expect(logger.warn.mock.calls.length).toBe(1) expect(connectorStatus.status).toBeUndefined() diff --git a/tests/utils/ErrorUtils.test.ts b/tests/utils/ErrorUtils.test.ts index de7a2a36..9da6f63d 100644 --- a/tests/utils/ErrorUtils.test.ts +++ b/tests/utils/ErrorUtils.test.ts @@ -1,4 +1,5 @@ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ + import { expect } from '@std/expect' import { describe, it } from 'node:test' -- 2.43.0