Skip to content

Commit e7756fd

Browse files
Optimizations (#2244)
* Translated to english * OPtimizations
1 parent 53943ed commit e7756fd

13 files changed

Lines changed: 729 additions & 720 deletions

src/lib/sandbox.ts

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ export function sandBox(
9797
}
9898
});
9999
} else {
100-
// IO-3: Object.assign statt Object.keys().forEach() – kein temporäres Keys-Array
100+
// IO-3: Object.assign instead of Object.keys().forEach() – no temporary keys array
101101
adapter.getForeignStates(pattern, (_err, _states) => _states && Object.assign(states, _states));
102102
}
103103
} else {
@@ -533,7 +533,7 @@ export function sandBox(
533533
if (!(adapter.config as JavaScriptAdapterConfig).subscribe && context.interimStateValues[id]) {
534534
// if the state is changed, we will compare it with interimStateValues
535535
const oldState = context.interimStateValues[id];
536-
// IO-1: for…in statt Object.keys().filter().every() – kein temporäres Array pro Aufruf
536+
// IO-1: for…in instead of Object.keys().filter().every() – no temporary array per call
537537
let stateHasChanged = false;
538538
for (const attr in stateAsObject) {
539539
if (attr === 'ts') {
@@ -1027,7 +1027,7 @@ export function sandBox(
10271027
}
10281028
}
10291029

1030-
// IO-2: O(1) Deduplizierung via Set statt O(n²) resUnique.includes()
1030+
// IO-2: O(1) deduplication via Set instead of O(n²) resUnique.includes()
10311031
const resUnique: string[] = [...new Set(res)];
10321032

10331033
for (let i = 0; i < resUnique.length; i++) {
@@ -1691,7 +1691,7 @@ export function sandBox(
16911691
if (oPattern?.id && Array.isArray(oPattern.id)) {
16921692
const result: (IobSchedule | string | null | undefined)[] = [];
16931693
for (let t = 0; t < oPattern.id.length; t++) {
1694-
// IO-4: Spread statt JSON.parse(JSON.stringify()) – kein tiefer Clone nötig (nur primitive Felder)
1694+
// IO-4: Spread instead of JSON.parse(JSON.stringify()) – no deep clone needed (only primitive fields)
16951695
const pa: Pattern = { ...oPattern, id: oPattern.id[t] };
16961696
result.push(
16971697
sandbox.subscribe(pa, callbackOrChangeTypeOrId, value) as
@@ -1944,7 +1944,7 @@ export function sandBox(
19441944

19451945
// Subscribe to all members of enum
19461946
for (const objId of members) {
1947-
// IO-6: `in` Operator statt Object.keys().includes() – O(1) statt O(n)
1947+
// IO-6: `in` operator instead of Object.keys().includes() – O(1) instead of O(n)
19481948
if (!(objId in subscriptions)) {
19491949
if (objects?.[objId]?.type === 'state') {
19501950
// Just subscribe to states
@@ -2653,14 +2653,14 @@ export function sandBox(
26532653
Object.keys(context.scripts).forEach(
26542654
name =>
26552655
context.scripts[name].schedules &&
2656-
// IO-8: Spread statt JSON.parse(JSON.stringify()) – _ioBroker hat nur primitive Felder
2656+
// IO-8: Spread instead of JSON.parse(JSON.stringify()) – _ioBroker has only primitive fields
26572657
context.scripts[name].schedules.forEach(s =>
26582658
schedules.push({ ...s._ioBroker } as unknown as ScheduleName),
26592659
),
26602660
);
26612661
} else {
26622662
script.schedules &&
2663-
// IO-8: Spread statt JSON.parse(JSON.stringify())
2663+
// IO-8: Spread instead of JSON.parse(JSON.stringify())
26642664
script.schedules.forEach(s => schedules.push({ ...s._ioBroker } as unknown as ScheduleName));
26652665
}
26662666
return schedules;
@@ -2846,13 +2846,14 @@ export function sandBox(
28462846
const removedScripts = new Set<string>();
28472847
for (let i = timers[id].length - 1; i >= 0; i--) {
28482848
if (timerId === undefined || timers[id][i].id === timerId) {
2849+
const clearedTimerId = timers[id][i].id;
28492850
removedScripts.add(timers[id][i].scriptName);
28502851
clearTimeout(timers[id][i].t);
28512852
if (timerId !== undefined) {
28522853
timers[id].splice(i, 1);
28532854
}
28542855
if (sandbox.verbose) {
2855-
sandbox.log(`clearStateDelayed: clear timer ${timers[id][i]?.id ?? timerId}`, 'info');
2856+
sandbox.log(`clearStateDelayed: clear timer ${clearedTimerId}`, 'info');
28562857
}
28572858
}
28582859
}
@@ -2863,15 +2864,22 @@ export function sandBox(
28632864
delete timers[id];
28642865
}
28652866
}
2866-
// IO-7: timersByScript Reverse-Index aktualisieren wenn State keine Timer mehr hat
2867-
if (!timers[id]) {
2867+
// IO-7: keep the timersByScript reverse-index in sync. For every script whose
2868+
// timer(s) we just removed, drop `id` from its set – unless that script still has
2869+
// another timer for this state (other scripts' timers may keep timers[id] alive).
2870+
if (removedScripts.size) {
2871+
const remaining = timers[id]; // undefined if the whole entry was deleted
28682872
for (const scriptName of removedScripts) {
28692873
const stateIds = context.timersByScript.get(scriptName);
2870-
if (stateIds) {
2871-
stateIds.delete(id);
2872-
if (!stateIds.size) {
2873-
context.timersByScript.delete(scriptName);
2874-
}
2874+
if (!stateIds) {
2875+
continue;
2876+
}
2877+
if (remaining?.some(e => e.scriptName === scriptName)) {
2878+
continue;
2879+
}
2880+
stateIds.delete(id);
2881+
if (!stateIds.size) {
2882+
context.timersByScript.delete(scriptName);
28752883
}
28762884
}
28772885
}
@@ -4093,7 +4101,7 @@ export function sandBox(
40934101
errorInCallback(err as Error);
40944102
}
40954103
}, ms);
4096-
// IO-10: Set.add() – O(1) statt Array.push()
4104+
// IO-10: Set.add() – O(1) instead of Array.push()
40974105
script.intervals.add(int);
40984106

40994107
if (sandbox.verbose) {
@@ -4105,7 +4113,7 @@ export function sandBox(
41054113
return null;
41064114
},
41074115
clearInterval: function (id: NodeJS.Timeout): void {
4108-
// IO-10: Set.has/delete – O(1) statt Array.indexOf+splice O(n)
4116+
// IO-10: Set.has/delete – O(1) instead of Array.indexOf+splice O(n)
41094117
if (script.intervals.has(id)) {
41104118
if (sandbox.verbose) {
41114119
sandbox.log('clearInterval() => cleared', 'info');
@@ -4121,7 +4129,7 @@ export function sandBox(
41214129
setTimeout: function (callback: (args?: any[]) => void, ms: number, ...args: any[]): NodeJS.Timeout | null {
41224130
if (typeof callback === 'function') {
41234131
const to = setTimeout(() => {
4124-
// IO-10: Set.delete – O(1) statt Array.indexOf+splice O(n)
4132+
// IO-10: Set.delete – O(1) instead of Array.indexOf+splice O(n)
41254133
script.timeouts.delete(to);
41264134

41274135
try {
@@ -4133,15 +4141,15 @@ export function sandBox(
41334141
if (sandbox.verbose) {
41344142
sandbox.log(`setTimeout(ms=${ms})`, 'info');
41354143
}
4136-
// IO-10: Set.add – O(1) statt Array.push
4144+
// IO-10: Set.add – O(1) instead of Array.push
41374145
script.timeouts.add(to);
41384146
return to;
41394147
}
41404148
sandbox.log(`Invalid callback for setTimeout! - ${typeof callback}`, 'error');
41414149
return null;
41424150
},
41434151
clearTimeout: function (id: NodeJS.Timeout): void {
4144-
// IO-10: Set.has/delete – O(1) statt Array.indexOf+splice O(n)
4152+
// IO-10: Set.has/delete – O(1) instead of Array.indexOf+splice O(n)
41454153
if (script.timeouts.has(id)) {
41464154
if (sandbox.verbose) {
41474155
sandbox.log('clearTimeout() => cleared', 'info');

src/main.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,6 @@ class JavaScript extends Adapter {
327327
/** Fast O(1) lookup set – always kept in sync with stateIds */
328328
private readonly stateIdSet: Set<string> = new Set();
329329

330-
/** Precomputed "from" string for prepareStateObject – avoids string alloc on every setState */
331330
private readonly subscriptions: SubscriptionResult[] = [];
332331
private readonly subscriptionsFile: FileSubscriptionResult[] = [];
333332
private readonly subscriptionsObject: SubscribeObject[] = [];
@@ -849,8 +848,6 @@ class JavaScript extends Adapter {
849848
async onReady(): Promise<void> {
850849
this.errorLogFunction = this.log;
851850
this.context.errorLogFunction = this.log;
852-
// Precompute once – avoids string template alloc on every setState call
853-
854851
this.config.maxSetStatePerMinute = parseInt(this.config.maxSetStatePerMinute as unknown as string, 10) || 1000;
855852
this.config.maxTriggersPerScript = parseInt(this.config.maxTriggersPerScript as unknown as string, 10) || 100;
856853

@@ -2186,7 +2183,8 @@ class JavaScript extends Adapter {
21862183

21872184
// remember all IDs – sort once to guarantee the sorted invariant
21882185
// required by binaryIndexOf() / sortedInsert() used later
2189-
for (const id of Object.keys(res).sort()) {
2186+
const keys = Object.keys(res).sort();
2187+
for (const id of keys) {
21902188
this.stateIds.push(id);
21912189
this.stateIdSet.add(id);
21922190
}

0 commit comments

Comments
 (0)