Immer patches for Array are correct, yet inefficient. Suggesting a new algorithm for optimized patches
I maintainer di solito rispondono entro 4 giorni
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 25/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Ferma
- Stack tecnologico
- javascript, typescript
- Ambito
- performance
Direzione di ricerca
Inizia con il test delle patch degli array in tests/patch.js, in particolare con il caso "arrays - multiple prepend" alle righe indicate. Confronta le risultato atteso attuale delle patch con il risultato proposto, quindi valuta l’algoritmo di matching limitato suggerito rispetto a prepend, splice e ad altre modifiche agli array. Il lavoro è completato quando il comportamento ottimizzato rimane corretto e riduce le patch non necessarie per piccole modifiche agli array.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
I am thinking as offering it as a pull request - let me know what you think
🚀 Feature Proposal
Today when computing a patch on arrays, immer compares objects by index, which results in all array change in case of unshift or splice usage. An example is the following test taken from immer testing -
https://github.com/immerjs/immer/blob/main/__tests__/patch.js#L543-L559
describe("arrays - multiple prepend", () => {
runPatchTest(
{x: [1, 2, 3]},
d => {
d.x.unshift(4)
d.x.unshift(5)
// 4,5,1,2,3
},
[
{op: "replace", path: ["x", 0], value: 5},
{op: "replace", path: ["x", 1], value: 4},
{op: "replace", path: ["x", 2], value: 1},
{op: "add", path: ["x", 3], value: 2},
{op: "add", path: ["x", 4], value: 3}
]
)
})
the expected result should be instead
[
{op: "add", path: ["x", 0], value: 5},
{op: "add", path: ["x", 1], value: 4}
]
Motivation
I am working on a new framework that also serializes patches, and the above is a performance issue.
Consider the above case - for an array of object, lets say an array of 100 objects with 10 attributes each, the current algorithm will generate 1000 patches, while my suggestion is to produce only 1 per added / removed object
Can this be solved in user-land code?
no
Example
See the example above.
Usage: immer -> serialize -> deserialize -> patched object
suggested algorithm
(pseudo code)
the problem with json diff is that given two arrays, without any additional knowledge, to figure out if an item was
pushed to the front, we have to do a === comparison between the array items, which is O(n^2) complexity.
for (let a = 0; a < A.length; a++) {
for (let b = 0; b < A.length; b++) {
if (A[a] === B[b])
// compute the diff
}
}
However, we can create an algorithm focused on small changes that has complexity O(n) with a cutoff.
The algorithm makes the assumption that small changes can be found fast and require small number of mutations to describe.
The cutoff is set at let limit = log(min(A.length, B.length)) and the algorithm has complexity O(limit^2) ~ O(n)
The algorithm -
let limit = log(min(A.length, B.length));
let a=0, b=0;
mainLoop: while (a < A.length && b < B.length) {
if (A(a) === B(b)) {
a += 1;
b += 1
}
continue;
for (let seekSize = 1; seekSize < limit; seekSize++) {
for (let index = 1; index <= seekSize; index++) {
if (A[a+index] === B[b+seekSize-index])
// we have a match, the elements from A between (a..a+index) and replace them with the items from B between (b..b+seekSize-index)
continue mainLoop;
}
}
// revert to direct comparison of attributes json diff model (the standard model used by all other algorithms)
}
- Lingua principale
- JavaScript
- Stelle
- 29k
- Fork
- 905
- Merge medio
- 3g 16h
- PR unite (30g)
- 22
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di immerjs/immer
-
Shrinking an array with `length =` and growing it back loses the patches for the truncated indicesForse già presa @RClaudiuM l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
I maintainer di solito rispondono entro 4 giorni
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 35/100
I maintainer di solito rispondono entro 4 giorni
-
Docs: Chinese (zh-CN) website translation is outdated vs English docsForse di nuovo libera @lijiayou0728 l’ha presa 91 giorni fa e non c’è nessuna pull request aperta. Aperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 55/100
immerjs/immer#1242 · 5 commenti ·
I maintainer di solito rispondono entro 4 giorni
-
question
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
I maintainer di solito rispondono entro 4 giorni
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
immerjs/immer#1217 · 1 commento ·
I maintainer di solito rispondono entro 4 giorni
Tutte le issue di immerjs/immer
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
Automattic/node-canvas#2633 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
capricorn86/happy-dom#2594 ·
I maintainer di solito rispondono entro 1 giorno
-
Decoding tag 1 (epoch date) with an 8-byte integer throws "Cannot mix BigInt and other types"Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 79/100
microsoft/monaco-editor#5575 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
I maintainer di solito rispondono entro 1 giorno