Fix perf issues with lazy sets
This commit is contained in:
parent
e5ccd070f6
commit
b58e0799e2
|
@ -24,21 +24,17 @@ const merge = (targetSet, toMerge) => {
|
|||
/**
|
||||
* @template T
|
||||
* @param {Set<Iterable<T>>} targetSet set where iterables should be added
|
||||
* @param {Array<Iterable<T> | LazySet<T>>} toDeepMerge iterables or lazy set to be flattened
|
||||
* @param {Array<LazySet<T>>} toDeepMerge lazy sets to be flattened
|
||||
* @returns {void}
|
||||
*/
|
||||
const flatten = (targetSet, toDeepMerge) => {
|
||||
for (const set of toDeepMerge) {
|
||||
if (set instanceof LazySet) {
|
||||
if (set._set.size > 0) targetSet.add(set._set);
|
||||
if (set._needMerge) {
|
||||
for (const mergedSet of set._toMerge) {
|
||||
targetSet.add(mergedSet);
|
||||
}
|
||||
flatten(targetSet, set._toDeepMerge);
|
||||
if (set._set.size > 0) targetSet.add(set._set);
|
||||
if (set._needMerge) {
|
||||
for (const mergedSet of set._toMerge) {
|
||||
targetSet.add(mergedSet);
|
||||
}
|
||||
} else {
|
||||
targetSet.add(set);
|
||||
flatten(targetSet, set._toDeepMerge);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -58,7 +54,7 @@ class LazySet {
|
|||
this._set = new Set(iterable);
|
||||
/** @type {Set<Iterable<T>>} */
|
||||
this._toMerge = new Set();
|
||||
/** @type {Array<Iterable<T> | LazySet<T>>} */
|
||||
/** @type {Array<LazySet<T>>} */
|
||||
this._toDeepMerge = [];
|
||||
this._needMerge = false;
|
||||
this._deopt = false;
|
||||
|
@ -76,6 +72,14 @@ class LazySet {
|
|||
this._needMerge = false;
|
||||
}
|
||||
|
||||
_isEmpty() {
|
||||
return (
|
||||
this._set.size === 0 &&
|
||||
this._toMerge.size === 0 &&
|
||||
this._toDeepMerge.length === 0
|
||||
);
|
||||
}
|
||||
|
||||
get size() {
|
||||
if (this._needMerge) this._merge();
|
||||
return this._set.size;
|
||||
|
@ -101,13 +105,19 @@ class LazySet {
|
|||
_set.add(item);
|
||||
}
|
||||
} else {
|
||||
this._toDeepMerge.push(iterable);
|
||||
this._needMerge = true;
|
||||
// Avoid being too memory hungry
|
||||
if (this._toDeepMerge.length > 100000) {
|
||||
this._flatten();
|
||||
if (this._toMerge.size > 100000) this._merge();
|
||||
if (iterable instanceof LazySet) {
|
||||
if (!iterable._isEmpty()) {
|
||||
this._toDeepMerge.push(iterable);
|
||||
this._needMerge = true;
|
||||
if (this._toDeepMerge.length > 100000) {
|
||||
this._flatten();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this._toMerge.add(iterable);
|
||||
this._needMerge = true;
|
||||
}
|
||||
if (this._toMerge.size > 100000) this._merge();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
const LazySet = require("../lib/util/LazySet");
|
||||
|
||||
describe("LazySet", () => {
|
||||
it("addAll", () => {
|
||||
const a = new Set(["a"]);
|
||||
const sut = new LazySet(a);
|
||||
const empty = new LazySet([]);
|
||||
expect(sut.size).toBe(1);
|
||||
sut.addAll(empty);
|
||||
expect(sut._toDeepMerge).toStrictEqual([]);
|
||||
expect(sut.size).toBe(1);
|
||||
const b = new Set(["b"]);
|
||||
sut.addAll(b);
|
||||
expect(sut._toMerge).toContain(b);
|
||||
expect(sut.size).toBe(2);
|
||||
const c = new LazySet(["c"]);
|
||||
sut.addAll(c);
|
||||
expect(sut._toDeepMerge).toContain(c);
|
||||
expect(sut.size).toBe(3);
|
||||
expect(sut._toDeepMerge).toStrictEqual([]);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue