Skip to content

Commit

Permalink
joh/cautious cephalopod (#184692)
Browse files Browse the repository at this point in the history
* improve performance of `TraitSpliceable#splice`, avoid O(n2), avoid loop when not removing anything

#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 <joao.moreno@microsoft.com>
  • Loading branch information
jrieken and joaomoreno committed Jun 12, 2023
1 parent bfffb9d commit b0bcc33
Showing 1 changed file with 26 additions and 9 deletions.
35 changes: 26 additions & 9 deletions src/vs/base/browser/ui/list/listWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,17 +129,30 @@ class Trait<T> implements ISpliceable<boolean>, IDisposable {

const diff = elements.length - deleteCount;
const end = start + deleteCount;
const sortedIndexes = [
...this.sortedIndexes.filter(i => i < start),
...elements.map((hasTrait, i) => hasTrait ? i + start : -1).filter(i => i !== -1),
...this.sortedIndexes.filter(i => i >= end).map(i => i + diff)
];
const sortedIndexes: number[] = [];
let firstSortedIndex: number | undefined = undefined;
let i = 0;

while (i < this.sortedIndexes.length && this.sortedIndexes[i] < start) {
sortedIndexes.push(this.sortedIndexes[i++]);
}

for (let j = 0; j < elements.length; j++) {
if (elements[j]) {
sortedIndexes.push(j + start);
firstSortedIndex = firstSortedIndex ?? sortedIndexes[sortedIndexes.length - 1];
}
}

while (i < this.sortedIndexes.length && this.sortedIndexes[i] >= end) {
sortedIndexes.push(this.sortedIndexes[i++] + diff);
firstSortedIndex = firstSortedIndex ?? sortedIndexes[sortedIndexes.length - 1];
}

const length = this.length + diff;

if (this.sortedIndexes.length > 0 && sortedIndexes.length === 0 && length > 0) {
const first = this.sortedIndexes.find(index => index >= start) ?? length - 1;
sortedIndexes.push(Math.min(first, length - 1));
sortedIndexes.push(Math.min(firstSortedIndex ?? length - 1, length - 1));
}

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

splice(start: number, deleteCount: number, elements: T[]): void {
if (!this.identityProvider) {
return this.trait.splice(start, deleteCount, elements.map(() => false));
return this.trait.splice(start, deleteCount, new Array(elements.length).fill(false));
}

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

const pastElementsWithTraitSet = new Set(pastElementsWithTrait);
const elementsWithTrait = elements.map(e => pastElementsWithTraitSet.has(this.identityProvider!.getId(e).toString()));
this.trait.splice(start, deleteCount, elementsWithTrait);
}
}
Expand Down

0 comments on commit b0bcc33

Please sign in to comment.