Browse Source

chore: improve list-diff perf

pull/27/head
Antoine Lanoe 7 months ago
parent
commit
3a38a252e8
  1. 20
      src/lib/list-diff/index.ts
  2. 211
      src/lib/list-diff/list-diff.test.ts

20
src/lib/list-diff/index.ts

@ -83,26 +83,26 @@ export const getListDiff = <T>( @@ -83,26 +83,26 @@ export const getListDiff = <T>(
return formatSingleListDiff(prevList as T[], LIST_STATUS.DELETED, options);
}
const diff: ListDiff["diff"] = [];
const prevIndexMatches: number[] = [];
const prevIndexMatches = new Set<number>();
nextList.forEach((nextValue, i) => {
const prevIndex = prevList.findIndex((prevValue, prevIdx) => {
if (prevIndexMatches.has(prevIdx)) {
return false;
}
if (isReferencedObject(prevValue, options.referenceProperty)) {
if (isObject(nextValue)) {
return (
isEqual(
return isEqual(
prevValue[options.referenceProperty as string],
nextValue[options.referenceProperty as string],
) && !prevIndexMatches.includes(prevIdx)
);
}
return false;
}
return (
isEqual(prevValue, nextValue) && !prevIndexMatches.includes(prevIdx)
);
return isEqual(prevValue, nextValue);
});
if (prevIndex > -1) {
prevIndexMatches.push(prevIndex);
prevIndexMatches.add(prevIndex);
}
const indexDiff = prevIndex === -1 ? null : i - prevIndex;
if (indexDiff === 0 || options.ignoreArrayOrder) {
@ -141,8 +141,8 @@ export const getListDiff = <T>( @@ -141,8 +141,8 @@ export const getListDiff = <T>(
});
prevList.forEach((prevValue, i) => {
if (!prevIndexMatches.includes(i)) {
return diff.splice(i, 0, {
if (!prevIndexMatches.has(i)) {
return diff.push({
value: prevValue,
prevIndex: i,
newIndex: null,

211
src/lib/list-diff/list-diff.test.ts

@ -102,20 +102,6 @@ describe("getListDiff", () => { @@ -102,20 +102,6 @@ describe("getListDiff", () => {
indexDiff: 0,
status: "equal",
},
{
value: "mendes",
prevIndex: 1,
newIndex: null,
indexDiff: null,
status: "deleted",
},
{
value: "verratti",
prevIndex: 2,
newIndex: null,
indexDiff: null,
status: "deleted",
},
{
value: "messi",
prevIndex: null,
@ -130,6 +116,20 @@ describe("getListDiff", () => { @@ -130,6 +116,20 @@ describe("getListDiff", () => {
indexDiff: -1,
status: "moved",
},
{
value: "mendes",
prevIndex: 1,
newIndex: null,
indexDiff: null,
status: "deleted",
},
{
value: "verratti",
prevIndex: 2,
newIndex: null,
indexDiff: null,
status: "deleted",
},
],
});
});
@ -145,20 +145,6 @@ describe("getListDiff", () => { @@ -145,20 +145,6 @@ describe("getListDiff", () => {
indexDiff: 0,
status: "equal",
},
{
value: 234,
prevIndex: 1,
newIndex: null,
indexDiff: null,
status: "deleted",
},
{
value: 76,
prevIndex: 2,
newIndex: null,
indexDiff: null,
status: "deleted",
},
{
value: 200,
prevIndex: null,
@ -173,6 +159,20 @@ describe("getListDiff", () => { @@ -173,6 +159,20 @@ describe("getListDiff", () => {
indexDiff: -1,
status: "moved",
},
{
value: 234,
prevIndex: 1,
newIndex: null,
indexDiff: null,
status: "deleted",
},
{
value: 76,
prevIndex: 2,
newIndex: null,
indexDiff: null,
status: "deleted",
},
],
});
});
@ -194,13 +194,6 @@ describe("getListDiff", () => { @@ -194,13 +194,6 @@ describe("getListDiff", () => {
type: "list",
status: "updated",
diff: [
{
value: { name: "joe", age: 87 },
prevIndex: 0,
newIndex: null,
indexDiff: null,
status: "deleted",
},
{
value: { name: "paul", age: 32 },
prevIndex: 2,
@ -222,6 +215,13 @@ describe("getListDiff", () => { @@ -222,6 +215,13 @@ describe("getListDiff", () => {
indexDiff: 1,
status: "moved",
},
{
value: { name: "joe", age: 87 },
prevIndex: 0,
newIndex: null,
indexDiff: null,
status: "deleted",
},
],
});
});
@ -335,13 +335,7 @@ describe("getListDiff", () => { @@ -335,13 +335,7 @@ describe("getListDiff", () => {
indexDiff: -5,
status: "moved",
},
{
value: true,
prevIndex: 2,
newIndex: null,
indexDiff: null,
status: "deleted",
},
{
value: true,
prevIndex: 1,
@ -370,13 +364,6 @@ describe("getListDiff", () => { @@ -370,13 +364,6 @@ describe("getListDiff", () => {
indexDiff: 0,
status: "equal",
},
{
value: 13,
prevIndex: 7,
newIndex: null,
indexDiff: null,
status: "deleted",
},
{
value: false,
prevIndex: null,
@ -391,6 +378,20 @@ describe("getListDiff", () => { @@ -391,6 +378,20 @@ describe("getListDiff", () => {
indexDiff: null,
status: "added",
},
{
value: true,
prevIndex: 2,
newIndex: null,
indexDiff: null,
status: "deleted",
},
{
value: 13,
prevIndex: 7,
newIndex: null,
indexDiff: null,
status: "deleted",
},
],
});
});
@ -423,20 +424,6 @@ describe("getListDiff", () => { @@ -423,20 +424,6 @@ describe("getListDiff", () => {
type: "list",
status: "updated",
diff: [
{
value: true,
prevIndex: 2,
newIndex: null,
indexDiff: null,
status: "deleted",
},
{
value: 13,
prevIndex: 7,
newIndex: null,
indexDiff: null,
status: "deleted",
},
{
value: false,
prevIndex: null,
@ -451,6 +438,20 @@ describe("getListDiff", () => { @@ -451,6 +438,20 @@ describe("getListDiff", () => {
indexDiff: null,
status: "added",
},
{
value: true,
prevIndex: 2,
newIndex: null,
indexDiff: null,
status: "deleted",
},
{
value: 13,
prevIndex: 7,
newIndex: null,
indexDiff: null,
status: "deleted",
},
],
});
});
@ -536,13 +537,6 @@ describe("getListDiff", () => { @@ -536,13 +537,6 @@ describe("getListDiff", () => {
type: "list",
status: "updated",
diff: [
{
value: "hello",
prevIndex: 0,
newIndex: null,
indexDiff: null,
status: "deleted",
},
{
value: { id: 8, age: 77 },
prevIndex: 4,
@ -572,18 +566,25 @@ describe("getListDiff", () => { @@ -572,18 +566,25 @@ describe("getListDiff", () => {
status: "equal",
},
{
value: { id: 55, character: { strength: 66 } },
prevIndex: 5,
value: { id: 99, character: { strength: 69 } },
prevIndex: null,
newIndex: 4,
indexDiff: null,
status: "added",
},
{
value: "hello",
prevIndex: 0,
newIndex: null,
indexDiff: null,
status: "deleted",
},
{
value: { id: 99, character: { strength: 69 } },
prevIndex: null,
newIndex: 4,
value: { id: 55, character: { strength: 66 } },
prevIndex: 5,
newIndex: null,
indexDiff: null,
status: "added",
status: "deleted",
},
],
});
@ -646,13 +647,6 @@ describe("getListDiff", () => { @@ -646,13 +647,6 @@ describe("getListDiff", () => {
type: "list",
status: "updated",
diff: [
{
value: "hello",
prevIndex: 0,
newIndex: null,
indexDiff: null,
status: "deleted",
},
{
value: { id: 8, age: 77 },
prevIndex: 4,
@ -682,18 +676,25 @@ describe("getListDiff", () => { @@ -682,18 +676,25 @@ describe("getListDiff", () => {
status: "equal",
},
{
value: { id: 55, character: { strength: 66 } },
prevIndex: 5,
value: { id: 99, character: { strength: 69 } },
prevIndex: null,
newIndex: 4,
indexDiff: null,
status: "added",
},
{
value: "hello",
prevIndex: 0,
newIndex: null,
indexDiff: null,
status: "deleted",
},
{
value: { id: 99, character: { strength: 69 } },
prevIndex: null,
newIndex: 4,
value: { id: 55, character: { strength: 66 } },
prevIndex: 5,
newIndex: null,
indexDiff: null,
status: "added",
status: "deleted",
},
],
});
@ -790,3 +791,35 @@ describe("getListDiff", () => { @@ -790,3 +791,35 @@ describe("getListDiff", () => {
});
});
});
describe("Performance", () => {
it("should correctly stream diff for 10.000 entries", () => {
const generateLargeList = (size: number, idPrefix: string) => {
return Array.from({ length: size }, (_, i) => ({
id: `${idPrefix}-${i}`,
value: i,
}));
};
const prevList = generateLargeList(10_000, "prev");
const nextList = [
...generateLargeList(5000, "prev"),
...generateLargeList(5000, "next"),
];
const receivedChunks = getListDiff(prevList, nextList).diff;
const deletions = receivedChunks.filter(
(diff) => diff.status === LIST_STATUS.DELETED,
);
const additions = receivedChunks.filter(
(diff) => diff.status === LIST_STATUS.ADDED,
);
const updates = receivedChunks.filter(
(diff) => diff.status === LIST_STATUS.EQUAL,
);
expect(receivedChunks.length).toBe(15_000); // 5000 deletions + 5000 equal + 5000 additions
expect(deletions.length).toBe(5000);
expect(additions.length).toBe(5000);
expect(updates.length).toBe(5000);
});
});

Loading…
Cancel
Save