-
Notifications
You must be signed in to change notification settings - Fork 2k
[WIP][lexical] Feature: GenMap - A generational copy-on-write NodeMap implementation #7674
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
packages/lexical-utils/src/index.ts
Outdated
for (const [key, node] of editorState._nodeMap) { | ||
nodeMap.set(key, $cloneWithProperties(node)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I couldn't figure out why it was done this way, there aren't really any tests that exercise this properly. I could only guess that this was a bodge that would be better fixed by updating _cloneNotNeeded
accordingly?
packages/lexical-utils/src/index.ts
Outdated
editor._dirtyLeaves = new Set(); | ||
editor._dirtyElements.clear(); | ||
} else { | ||
editor._editorState = editorState; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code didn't do anything at all if there was no active state, this seemed like the right thing to do? Not really sure without good tests either way.
Description
Replace the naïve Map implementation of NodeMap with a version optimized for structural sharing when the Map is over a size threshold (>= 1000 entries currently).
GenMap has two "modes" based on the
_mutable
flag:_old
from the previous_old
and_nursery
) or make a Shallow Copy of_nursery
before changing to mutable mode. This is the default state.Each GenMap contains two maps (both created on demand):
_old
- A read-only snapshot of some previous state (equivalent to an old Map based NodeMap), generated by the last collection_nursery
- The working set of nodes (or tombstones) that have changed from_old
. Tombstones are used to mark deletions of nodes that are still present in_old
but will be removed at the next collection. Whether or not this is safe to mutate directly is based on the_mutable
flag.A GenMap can be cloned from another GenMap. This will mark the previous GenMap as not mutable (so its nursery must be copied before use) and reference its
_old
and_nursery
directly.Terms
Collection is when the next
_old
is generated. Pseudocode:Shallow Copy is when a copy or the nursery is made (
_old
is not changed). Pseudocode:Notes
This is an optimization because the cost of copying a Map is linear in both memory and time. In large documents, most nodes are not updated on each update cycle, so we are only paying the cost to copy the smaller nursery. Occasionally we pay the full cost to do a collection, but this is amortized since we don't do it often.
Related:
Test plan
All existing suites pass
TODO