Skip to content

Commit b0bcc33

Browse files
jriekenjoaomoreno
andauthored
joh/cautious cephalopod (microsoft#184692)
* improve performance of `TraitSpliceable#splice`, avoid O(n2), avoid loop when not removing anything microsoft#184615 * improve `Trait#splice` by reducing how often arrays are iterated over (from eight to three) * one more cleanup --------- Co-authored-by: João Moreno <[email protected]>
1 parent bfffb9d commit b0bcc33

File tree

1 file changed

+26
-9
lines changed

1 file changed

+26
-9
lines changed

src/vs/base/browser/ui/list/listWidget.ts

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -129,17 +129,30 @@ class Trait<T> implements ISpliceable<boolean>, IDisposable {
129129

130130
const diff = elements.length - deleteCount;
131131
const end = start + deleteCount;
132-
const sortedIndexes = [
133-
...this.sortedIndexes.filter(i => i < start),
134-
...elements.map((hasTrait, i) => hasTrait ? i + start : -1).filter(i => i !== -1),
135-
...this.sortedIndexes.filter(i => i >= end).map(i => i + diff)
136-
];
132+
const sortedIndexes: number[] = [];
133+
let firstSortedIndex: number | undefined = undefined;
134+
let i = 0;
135+
136+
while (i < this.sortedIndexes.length && this.sortedIndexes[i] < start) {
137+
sortedIndexes.push(this.sortedIndexes[i++]);
138+
}
139+
140+
for (let j = 0; j < elements.length; j++) {
141+
if (elements[j]) {
142+
sortedIndexes.push(j + start);
143+
firstSortedIndex = firstSortedIndex ?? sortedIndexes[sortedIndexes.length - 1];
144+
}
145+
}
146+
147+
while (i < this.sortedIndexes.length && this.sortedIndexes[i] >= end) {
148+
sortedIndexes.push(this.sortedIndexes[i++] + diff);
149+
firstSortedIndex = firstSortedIndex ?? sortedIndexes[sortedIndexes.length - 1];
150+
}
137151

138152
const length = this.length + diff;
139153

140154
if (this.sortedIndexes.length > 0 && sortedIndexes.length === 0 && length > 0) {
141-
const first = this.sortedIndexes.find(index => index >= start) ?? length - 1;
142-
sortedIndexes.push(Math.min(first, length - 1));
155+
sortedIndexes.push(Math.min(firstSortedIndex ?? length - 1, length - 1));
143156
}
144157

145158
this.renderer.splice(start, deleteCount, elements.length);
@@ -226,12 +239,16 @@ class TraitSpliceable<T> implements ISpliceable<T> {
226239

227240
splice(start: number, deleteCount: number, elements: T[]): void {
228241
if (!this.identityProvider) {
229-
return this.trait.splice(start, deleteCount, elements.map(() => false));
242+
return this.trait.splice(start, deleteCount, new Array(elements.length).fill(false));
230243
}
231244

232245
const pastElementsWithTrait = this.trait.get().map(i => this.identityProvider!.getId(this.view.element(i)).toString());
233-
const elementsWithTrait = elements.map(e => pastElementsWithTrait.indexOf(this.identityProvider!.getId(e).toString()) > -1);
246+
if (pastElementsWithTrait.length === 0) {
247+
return this.trait.splice(start, deleteCount, new Array(elements.length).fill(false));
248+
}
234249

250+
const pastElementsWithTraitSet = new Set(pastElementsWithTrait);
251+
const elementsWithTrait = elements.map(e => pastElementsWithTraitSet.has(this.identityProvider!.getId(e).toString()));
235252
this.trait.splice(start, deleteCount, elementsWithTrait);
236253
}
237254
}

0 commit comments

Comments
 (0)