-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
Transform.insertNodes & Transform.insertFragment performance optimize #5543
Conversation
🦋 Changeset detectedLatest commit: d01c912 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
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.
Looks promising, will review asap
16bd79d
to
a0d64d0
Compare
added |
hey, any progress about this? |
Apologies, life was a bit hectic recently. Will look at this shortly. |
This PR is a subsequent optimization of the previous PR.
Why does insertNodes/insertFragment have performance issues?
Each editor instance has a corresponding
dirtyPaths
, used to judge which nodeEntry to executenormalizeNode
.Path.levels(path)
andnode descendants
paths will be added to dirtyPathswithoutNormalizing
), normalizeNode will be delayed, and the existing dirtyPaths need to be path transformed with subsequent ops on each apply.Since slate is a collaborative editor based on OT, an insertNodes/insertFragment command will be converted into many Ops. for example,
insertNodes
withn
nodes will eventually be converted inton
insertNode Ops
Assume there is no dirtyPath before insertNodes,
n
text nodes are inserted, and the depth of inserted path isd
d
dirtyPaths are generatedd
dirtyPaths, executePath.levels(p)
once, and the total number of dirtyPaths isd+1
. (according toPath.transform
logic)d + 1
dirtyPaths, executePath.levels(p)
once, and the total number of dirtyPaths isd+2
d + n - 2
dirtyPaths, executePath.levels(p)
once, and the total number of dirtyPaths isd + n - 1
so finally
(n - 1) * d + d * (n - 2) * (n - 1) / 2
times of path transform andn - 1
times ofPath.levels
were executed. The complexity isO(n2)
If you insert
n
block nodes with complex children or into a higher depth, the time will also increase multiply.how to optimize
For insertNodes. It is not necessary to perform transform on the dirtyPath generated by the preceding insertNode op. because:
Path.compare
result is 1)Path.levels
every timeSo we can batch update the dirtyPaths of the n node insert. Proceed as follows:
and In order to implement this , we need to allow dirty paths batch update outside of apply。
benchmark
test code
test environment
result
Checks
yarn test
.yarn lint
. (Fix errors withyarn fix
.)yarn start
.)yarn changeset add
.)