Performance: merges with many heads and commits with many scattered edits (patch_make O(N·k), candidate diffs)
I maintainer di solito rispondono entro 1 giorno
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à
- Attiva
- Stack tecnologico
- node.js, typescript
- Ambito
- backend, performance
Direzione di ricerca
Start by reading the recordMerge and makePatch paths mentioned in the issue, then inspect the diff-match-patch patch_make implementation and its tests. Compare the proposed work in the stated order: P1, P3, P2, then P4; each item is intended as a separate PR with probes. Done means the selected change meets its stated correctness and replay requirements and includes measurements; the probes are available on request.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Merges with many heads, and commits with many scattered edits in large text, are slow, and their transient memory is high. The cost is mostly in makePatch, through diff-match-patch's patch_make, and recordMerge multiplies it.
Measurements
Each case ran in a fresh Node 26 process with main at bdd325c (plus #25). The figures are wall time and peak RSS (maxRSS).
A db document with string columns, merge3 on records (immer-db codec)
-
Shape: 20 records of 256 KiB text (5 MiB in total). Each of 8 heads edits every third line of every record (each head its own lines).
-
Applying the 7 remote heads: 17 s; 7
merge3calls account for 16 s. -
The merge commit: 64 s, in 9
makePatchcalls (the patch, plus 8 candidate diffs inrecordMerge), about 7 s each. -
Peak RSS: 0.66 GB.
-
Scaling at 1 MiB with the same shape:
heads apply heads + merge commit 8 18.6 s 16 23.0 s 32 30.7 s Peak RSS rises from 0.35 to 0.59 GB.
-
Few edits are cheap: the same documents with a few edited records take under 1 s, and less than 0.2 GB, even at 32 heads.
-
0.13.0 behaves the same.
StringDocument with mergeStrings3
- Shape: 380 KB, 8 heads, each editing a third of its lines.
- The merge commit: 7.5 s, and it raises peak RSS by 1.8 GB. Each of the 8 candidate diffs raises it by 0.4 to 0.46 GB.
diff-match-patch alone (diffTimeout 0.2 s), text with k scattered edits
| text | edits | diff_main |
patch_make |
|---|---|---|---|
| 371 KB | 100 | 22 ms | 75 ms |
| 371 KB | 1,000 | 110 ms, +21 MB | 728 ms, +65 MB |
| 1 MB | 1,000 | 105 ms, +31 MB | 1,690 ms, +103 MB |
| 1 MB | 4,000 | 234 ms (timed out) | 235 ms (timed out) |
The CPU profile of patch_make (1 MB, 1,000 edits) shows two hot spots:
patch_addContext_, 67%: for each patch it callsindexOfandlastIndexOfon the whole text, to grow the context until it is unique;patch_makeitself, 19%: it rebuildspostpatchTextwithsubstringand concatenation after every diff.
Both are $O(N \cdot k)$ for a text of length $N$ and $k$ patches.
Proposals (revised after review)
- P1. Bound
recordMerge's candidate diffs.- Diff at most 2 parents, in a canonical order: for example, the order in which
parentsis recorded. - Each candidate gives either a complete, valid
mergePatchor a refusal; never a partial result. - Each candidate diffs an exact parent value to the same immutable merged value. The recorded
mergeParentandmergePatchmust reconstruct that value, with deterministic tie-breaking. - The chosen
mergePatchis recorded in the patch, and every client replays the recorded result rather than recomputing it, so all clients get the same value. - This changes record sizes, so callers that measure a commit before making it should keep using
previewCommit. - A budget checked between
makePatchcalls can't bound one pathological call. So eithermakePatchgets a deterministic work budget of its own (see P3), or the caller runs the merge where it can be stopped.
- Diff at most 2 parents, in a canonical order: for example, the order in which
- P3. A deterministic diff bound (moved earlier).
- Replace the wall-clock
diffTimeoutwith a work-based bound (for example, counted operations indiff_main's bisect), so that the same inputs always give the same patch on any machine. - Today the cutoff depends on CPU speed, so a commit's patch, and its size, aren't reproducible.
- Replace the wall-clock
- P2. A byte-identical
patch_makeoptimization (in @cocalc/diff-match-patch).- Derive the post-patch text from the original texts and offsets, instead of rebuilding it with
substringand concatenation after every diff. - The output must be byte-identical. Tests compare the old and new implementations on corpora, including repetitive text, and the change is measured.
- This speeds up only
patch_make's assembly;diff_mainkeeps its own (P3) bound. It doesn't make diffing linear end to end.
- Derive the post-patch text from the original texts and offsets, instead of rebuilding it with
- P2b (optional, later). Bound
patch_addContext_'s uniqueness search.-
This changes the context of generated patches in repetitive text, so it would be a separate, versioned change, with these tests:
- exact reconstruction;
- mixed-version replay, where old and new clients apply each other's patches;
- ambiguous fuzzy replay;
- cross-version golden tests;
- repetitive text, and insertion and deletion drift;
- an audit of legacy-history replay that still uses
merge3or fuzzy application.
Old replay semantics are preserved, or the change in behavior is versioned.
-
- P4. Byte-based cache sizes for db documents.
- The value and exact-value caches use
count()insizeCalculation. For a db document that is the number of records, so the 10 M size limit doesn't bound bytes; only the entry limits (100 and 2,000) do.
- The value and exact-value caches use
Order: P1, P3, P2, P4, then P2b (optional). Separate PRs, each with its own probes. The probes are available on request.
- Lingua principale
- TypeScript
- Stelle
- 0
- Fork
- 0
- Merge medio
- 4h 2m
- PR unite (30g)
- 34
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Nessuna guida per i contributori
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 sagemathinc/patchflow
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
sagemathinc/patchflow#35 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di sagemathinc/patchflow
Issue simili
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 91/100
caelestia-dots/caelestia#534 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
bobadilla-tech/biasmarket.com#402 ·
I maintainer di solito rispondono entro 1 giorno
-
bug good first issue
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
javvadivijayprasad/sel2pw#28 ·
-
Area: Infrastructure Chore Difficulty: Low Good First Issue Priority: Low
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
DouglasNeuroInformatics/OpenDataCapture#1836 ·
I maintainer di solito rispondono entro 1 giorno
-
Two wording fixes: the init PROVIDER comment and the confirm page's ledeForse già presa @kurtbruns l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 83/100
I maintainer di solito rispondono entro 1 giorno