Skip to content

Multi-device editing/syncing with CRDTs#250

Description

@trishume

This is a tracking issue/roadmap/plan for how I'm going to proceed with adding the ability to synchronize documents. The tasks below correspond approximately to PRs I plan on writing and the order I plan on doing them.

Edit 2017/08/04: 馃摑 馃憗 I wrote a detailed document describing the CRDT

Edit 2017/05/04: Add more detail.
Edit 2017/05/04: Add ideas for optimizing
Edit 2017/07/12: Heavily refactored list to reflect what actually happened, include links to more PRs, and update plan

cc @raphlinus

xi-rope refactoring

Prior to starting this project, the rope and mini-CRDT data structures were mostly undocumented, lightly tested and used some representations that didn't have good time complexity or didn't fit well with turning the mini-CRDT into a full CRDT. The first step of the project was to refactor and replace some of the existing data structures and algorithms and comment and test them.

Fuchsia last-write-wins prototype

As an initial use case of this functionality, implement syncing using ledger for fuchsia/xi.

CRDT Merge operation

Implement the merge function on Engine for histories not involving undo.

Integrate CRDT into Fuchsia

You can now open Xi on two Fuchsia devices and type into both of them concurrently and they will synchronize and reach a consistent state shortly afterward.

Documentation

Improve CRDT robustness and functionality

  • Write randomized tests for the merge operation. Possibly using quickcheck tests or fuzz tests. [WIP] Fuzz testing for xi-rope聽#300
  • Support Undo operations in the CRDT
  • Use test generator to generate large tests and characterize performance.

Make it fast

The above will have terrible awful scaling properties and will slow to a crawl in many use cases. The next step is to figure out ways to improve the CRDT representation and operations to have better time and space complexity. Some of these ideas are well thought out and are clear wins, others are more speculative half-baked ideas (marked by a "馃 ").

  • Properly compute the common base for merges, currently it always starts from the very first commit. This should be both easy and a huge improvement to merge performance.
  • Optimize merge for common simple cases like no new edits on one side, or no edits in common after the base. These won't be that common with conflicts but will be super frequent in the Ledger PageWatcher update case.
  • Talk to Ledger team about having side with more revisions be on the left of the merge.
  • Store larger Subsets in a rope with an aggregation on number of inserted and deleted characters so that calculations can do things in the middle of the text without being O(n).
  • Switch to a multi-key ledger representation, instead of storing everything in a single key. This will improve both running time due to not loading in large changes from ledger, as well as storage use in Ledger.
    • Refactor to make this possible, for example this requires that new changes be merged into the Ledger instead of the current Engine being put in, that will guarantee things are only appended.
    • Optimize the ledger storage serialization of revision history to store segments of history in separate keys, use changed keys in merge to determine common prefix.
    • Store text in ledger as a doubly-linked list of blocks. If a block grows too large it splits, and if too small it merges, but both of these are local operations affecting a constant small number of keys.
  • 馃 Store the revision history in a rope/tree/skip-list to make computing the coordinate transforms O(log n) instead of O(n) for merges and undos. Where n is the size of the history after the undo/common prefix. This would definitely be useful for undo because it would allow an arbitrarily long undo history without significant performance degradation, and would effectively allow us to remove the garbage collector.
  • 馃 In merge, combine transforms that are spatially separate into one Subset so that there are less Subsets to rebase and transform repeatedly in merge. Like Combine sequential edits with same priority in merge聽#351 but more extreme.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions