Skip to content

Commit cad54c4

Browse files
authored
refactor(utils): improve performance of copyEmptyArrayProps function (#1816)
* test(utils): add test for performance with large arrays * fix(utils): improve performance of copyEmptyArrayProps fn * fix(test): validate test with 200 ms * docs(release): add changeset
1 parent b07dbae commit cad54c4

3 files changed

Lines changed: 39 additions & 18 deletions

File tree

.changeset/wise-timers-shake.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@commercetools/sync-actions': minor
3+
---
4+
5+
feat(sync-actions): improve performance for large arrays comparisons"

packages/sync-actions/src/utils/copy-empty-array-props.js

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,46 +13,41 @@ const CUSTOM = 'custom'
1313
export default function copyEmptyArrayProps(oldObj = {}, newObj = {}) {
1414
if (!isNil(oldObj) && !isNil(newObj)) {
1515
const nextObjectWithEmptyArray = Object.entries(oldObj).reduce(
16-
(nextObject, [key, value]) => {
17-
const merged = {
18-
...newObj,
19-
...nextObject,
20-
}
21-
16+
(merged, [key, value]) => {
2217
// Ignore CUSTOM key as this object is dynamic and its up to the user to dynamically change it
2318
// todo, it would be better if we pass it as ignored keys param
2419
if (key === CUSTOM) return merged
2520

2621
if (Array.isArray(value) && newObj[key] && newObj[key].length >= 1) {
2722
/* eslint-disable no-plusplus */
23+
const hashMapValue = value.reduce((acc, val) => {
24+
acc[val.id] = val
25+
return acc
26+
}, {})
2827
for (let i = 0; i < newObj[key].length; i++) {
2928
if (
3029
!isNil(newObj[key][i]) &&
3130
typeof newObj[key][i] === 'object' &&
3231
!isNil(newObj[key][i].id)
3332
) {
3433
// Since its unordered array elements then check if the element on `oldObj` exists by id
35-
const foundObject = value.find(
36-
(v) => Number(v.id) === Number(newObj[key][i].id)
37-
)
34+
const foundObject = hashMapValue[newObj[key][i].id]
3835
if (!isNil(foundObject)) {
3936
const [, nestedObject] = copyEmptyArrayProps(
4037
foundObject,
4138
newObj[key][i]
4239
)
4340
/* eslint-disable no-param-reassign */
44-
newObj[key][i] = nestedObject
41+
merged[key][i] = nestedObject
4542
}
4643
}
4744
}
4845

4946
return merged
5047
}
5148
if (Array.isArray(value)) {
52-
return {
53-
...merged,
54-
[key]: isNil(newObj[key]) ? [] : newObj[key],
55-
}
49+
merged[key] = isNil(newObj[key]) ? [] : newObj[key]
50+
return merged
5651
}
5752
if (
5853
!isNil(newObj[key]) &&
@@ -62,10 +57,8 @@ export default function copyEmptyArrayProps(oldObj = {}, newObj = {}) {
6257
!(value instanceof Date)
6358
) {
6459
const [, nestedObject] = copyEmptyArrayProps(value, newObj[key])
65-
return {
66-
...merged,
67-
[key]: nestedObject,
68-
}
60+
merged[key] = nestedObject
61+
return merged
6962
}
7063
return merged
7164
},

packages/sync-actions/test/utils/copy-empty-array-props.spec.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { performance } from 'perf_hooks'
12
import copyEmptyArrayProps from '../../src/utils/copy-empty-array-props'
23

34
describe('null check on root value', () => {
@@ -306,3 +307,25 @@ test('shouldnt change objects since there is no arrays to copy', () => {
306307
expect(old).toEqual(oldObj)
307308
expect(fixedNewObj).toEqual(newObj)
308309
})
310+
311+
test('performance test for large arrays should be less than 200 ms', () => {
312+
const oldObj = {
313+
addresses: Array(5000)
314+
.fill(null)
315+
.map((a, index) => ({ id: `address-${index}` })),
316+
}
317+
318+
const newObj = {
319+
addresses: Array(5000)
320+
.fill(null)
321+
.map((a, index) => ({ id: `address-${index}` })),
322+
}
323+
324+
const start = performance.now()
325+
const [old, fixedNewObj] = copyEmptyArrayProps(oldObj, newObj)
326+
const end = performance.now()
327+
328+
expect(old).toEqual(oldObj)
329+
expect(fixedNewObj).toEqual(newObj)
330+
expect(end - start).toBeLessThan(200)
331+
})

0 commit comments

Comments
 (0)