Skip to content

Commit 3665357

Browse files
committed
fix(Scanner): Try to improve time complexity of Scanner
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
1 parent b9de31a commit 3665357

File tree

1 file changed

+62
-52
lines changed

1 file changed

+62
-52
lines changed

src/lib/Scanner.ts

Lines changed: 62 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import * as Parallel from 'async-parallel'
21
import Diff, { ActionType, CreateAction, MoveAction, RemoveAction, ReorderAction, UpdateAction } from './Diff'
32
import { Bookmark, Folder, ItemLocation, ItemType, TItem, TItemLocation } from './Tree'
43
import Logger from './Logger'
@@ -121,58 +120,57 @@ export default class Scanner<L1 extends TItemLocation, L2 extends TItemLocation>
121120
const stillUnmatched = new Set(newFolder.children)
122121

123122
// (using map here, because 'each' doesn't provide indices)
124-
await Parallel.map(
125-
oldFolder.children,
126-
async(old, index) => {
127-
const key = `${old.type}_${old.title}`
128-
const potentialMatches = unmatchedMap.get(key)
129-
let newItem = null
130-
if (potentialMatches) {
131-
const matchIndex = potentialMatches.findIndex((m) =>
132-
this.mergeable(old, m)
133-
)
134-
if (matchIndex !== -1) {
135-
newItem = potentialMatches.splice(matchIndex, 1)[0]
136-
stillUnmatched.delete(newItem)
137-
}
138-
}
139-
// we found an item in the new folder that matches the one in the old folder
140-
if (newItem) {
141-
await this.diffItem(old, newItem)
142-
return
123+
let index = 0
124+
for (const old of oldFolder.children) {
125+
const key = `${old.type}_${old.title}`
126+
const potentialMatches = unmatchedMap.get(key)
127+
let newItem = null
128+
if (potentialMatches) {
129+
const matchIndex = potentialMatches.findIndex((m) =>
130+
this.mergeable(old, m)
131+
)
132+
if (matchIndex !== -1) {
133+
newItem = potentialMatches.splice(matchIndex, 1)[0]
134+
stillUnmatched.delete(newItem)
143135
}
136+
}
137+
// we found an item in the new folder that matches the one in the old folder
138+
if (newItem) {
139+
await this.diffItem(old, newItem)
140+
index++
141+
continue
142+
}
144143

145-
if (newFolder.isRoot && newFolder.location === ItemLocation.LOCAL) {
146-
// We can't remove root folders locally
147-
return
148-
}
144+
if (newFolder.isRoot && newFolder.location === ItemLocation.LOCAL) {
145+
// We can't remove root folders locally
146+
index++
147+
continue
148+
}
149149

150-
this.result.REMOVE.commit({
151-
type: ActionType.REMOVE,
152-
payload: old,
153-
index,
154-
})
155-
},
156-
1
157-
)
150+
this.result.REMOVE.commit({
151+
type: ActionType.REMOVE,
152+
payload: old,
153+
index,
154+
})
155+
156+
index++
157+
}
158158

159159
// created Items
160-
// (using map here, because 'each' doesn't provide indices)
161-
await Parallel.map(
162-
Array.from(stillUnmatched.values()),
163-
async(newChild) => {
164-
if (oldFolder.isRoot && oldFolder.location === ItemLocation.LOCAL) {
165-
// We can't create root folders locally
166-
return
167-
}
168-
this.result.CREATE.commit({
169-
type: ActionType.CREATE,
170-
payload: newChild,
171-
index: newFolder.children.findIndex((child) => child === newChild),
172-
})
173-
},
174-
1
175-
)
160+
const childToIndex = new Map<TItem<L2>, number>()
161+
newFolder.children.forEach((child, i) => childToIndex.set(child, i))
162+
163+
for (const newChild of stillUnmatched) {
164+
if (oldFolder.isRoot && oldFolder.location === ItemLocation.LOCAL) {
165+
// We can't create root folders locally
166+
continue
167+
}
168+
this.result.CREATE.commit({
169+
type: ActionType.CREATE,
170+
payload: newChild,
171+
index: childToIndex.get(newChild),
172+
})
173+
}
176174
}
177175

178176
async diffBookmark(oldBookmark:Bookmark<L1>, newBookmark:Bookmark<L2>):Promise<void> {
@@ -230,7 +228,12 @@ export default class Scanner<L1 extends TItemLocation, L2 extends TItemLocation>
230228
keys.add(item.type)
231229

232230
for (const key of keys) {
233-
removedFuzzyMap.set(key, (removedFuzzyMap.get(key) || []).concat({ rootAction: action, item }))
231+
let list = removedFuzzyMap.get(key)
232+
if (!list) {
233+
list = []
234+
removedFuzzyMap.set(key, list)
235+
}
236+
list.push({ rootAction: action, item })
234237
}
235238
}
236239

@@ -275,8 +278,16 @@ export default class Scanner<L1 extends TItemLocation, L2 extends TItemLocation>
275278
const potentialSet = new Set<{ rootAction: RemoveAction<L1, L2>; item: TItem<L1> }>()
276279
for (const key of searchKeys) {
277280
const list = removedFuzzyMap.get(key)
278-
if (list && list.filter((m) => this.mergeable(m.item, createdItem)).length) {
279-
list.forEach(m => potentialSet.add(m))
281+
if (!list) continue
282+
let hasMergeable = false
283+
for (const m of list) {
284+
if (this.mergeable(m.item, createdItem)) {
285+
hasMergeable = true
286+
break
287+
}
288+
}
289+
if (hasMergeable) {
290+
list.forEach((m) => potentialSet.add(m))
280291
break
281292
}
282293
}
@@ -362,7 +373,6 @@ export default class Scanner<L1 extends TItemLocation, L2 extends TItemLocation>
362373

363374
await this.diffItem(oldItem, createdItem)
364375
hasNewActions = true
365-
break
366376
}
367377
}
368378

0 commit comments

Comments
 (0)