-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
Use TextNode.replaceData and TextNode.appendData #3703
Comments
The code change itself will not be very complex (will push PR soon) as we already have proper diff implementation ( However, the thing we should consider here is performance since this task changes simple value update: to complex "diffing and partial updates" strategy (note from @pjasiun that the When
|
PerformanceI started testing performance on editor instance, but it quickly became obvious that the bottleneck here is a The previous I placed the results here. It is clearly visible that replacing bigger part of the text causes diff to slow down for longer texts: Initial text length - 381 characters: Initial text length - 761 characters: |
SolutionOne of the biggest improvement we hope to achieve is improving composition handling (especially during collaborative scenarios). From what I checked it is broken now (FF for example): From some initial tests it seems this fix will not solve all issues I was able to generate with composition and programmatically inserting text (which simulates collaboration) in the same text node, but still there are other task waiting (#1342) so at the end it should improve composition/collaboration too IMHO. Due to the fact of poor
Initial text length - 1522 characters: |
One thing is unclear to me - how much does this solution help. You only mentioned that something is still broken on Firefox. But does it work better in general?
Because, if it does, I'd continue this research. One thing that I'm planning for a long time is a simpler diff method which would scan both strings from both ends and find first different characters. Text between these indexes needs to be replaced. This should be much faster and, at the same time, completely sufficient for cases like typing and rendering. I'm not even sure whether typing doesn't use this diffing mechanism already.
…Sent from my iPhone
On 22 Mar 2018, at 13:12, Krzysztof Krztoń ***@***.***> wrote:
Solution
One of the biggest improvement we hope to achieve is improving composition handling (especially during collaborative scenarios). From what I checked it is broken now (FF for example):
From some initial tests it seems this fix will not solve all issues I was able to generate with composition and programmatically inserting text (which simulates collaboration) in the same text node, but still there are other task waiting (#1342) so at the end it should improve composition/collaboration too IMHO.
Due to the fact of poor diff performance in some cases, I think we cannot use this solution for all scenarios. We may think of:
Not implementing it now, wait for other renderer improvements and get back to it when we will encounter issues directly caused by this (it will come sooner or later iMHO and then we will face the same problems as now - or maybe not and then we don't have to change it).
Go with the solution this ticket initially proposed, but limit diff usage to cases when compared texts are relatively short so we won't hit diff bottleneck. Still, performance depends on many external factors and there always be a case when someone has slower machine (so diff performs poorly) or encounters a case with longer texts which breaks something.
Look for other solution, but I'm not sure if there is any. Partial text node updates will always required some kind of diffing mechanism.
Use more performant diff function. The downside - there always will be some performance limit when such function starts to perform poorly. For faster functions it may be encounter just less frequently.
From what I have searched I found fastDiff library (it is on Apache License 2.0 and takes 25 KB unminified so I'm not sure if it would be suitable for CKEditor 5 - but it shows diffing can be faster) which is visibly faster than our current diff:
Initial text length - 1522 characters:
WDYT @Reinmar @pjasiun?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
PS. The idea behind this diff mechanism is that in our cases, atomic changes like typing are affecting only a narrow part of the text.
…Sent from my iPhone
On 22 Mar 2018, at 13:12, Krzysztof Krztoń ***@***.***> wrote:
Solution
One of the biggest improvement we hope to achieve is improving composition handling (especially during collaborative scenarios). From what I checked it is broken now (FF for example):
From some initial tests it seems this fix will not solve all issues I was able to generate with composition and programmatically inserting text (which simulates collaboration) in the same text node, but still there are other task waiting (#1342) so at the end it should improve composition/collaboration too IMHO.
Due to the fact of poor diff performance in some cases, I think we cannot use this solution for all scenarios. We may think of:
Not implementing it now, wait for other renderer improvements and get back to it when we will encounter issues directly caused by this (it will come sooner or later iMHO and then we will face the same problems as now - or maybe not and then we don't have to change it).
Go with the solution this ticket initially proposed, but limit diff usage to cases when compared texts are relatively short so we won't hit diff bottleneck. Still, performance depends on many external factors and there always be a case when someone has slower machine (so diff performs poorly) or encounters a case with longer texts which breaks something.
Look for other solution, but I'm not sure if there is any. Partial text node updates will always required some kind of diffing mechanism.
Use more performant diff function. The downside - there always will be some performance limit when such function starts to perform poorly. For faster functions it may be encounter just less frequently.
From what I have searched I found fastDiff library (it is on Apache License 2.0 and takes 25 KB unminified so I'm not sure if it would be suitable for CKEditor 5 - but it shows diffing can be faster) which is visibly faster than our current diff:
Initial text length - 1522 characters:
WDYT @Reinmar @pjasiun?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
Pushed initial changes to https://github.com/ckeditor/ckeditor5-engine/tree/t/403 (and also diff performance manual test to https://github.com/ckeditor/ckeditor5-utils/commits/t/ckeditor5-engine/403-diffperformance so it won't get lost on my local machine). |
@Reinmar, true I didn't dive deep enough into how it helps to say what is the real improvement. Partially because we have other things (like selection rerendering, element/children updates, etc) which we plan to improve, but the final flow may be hard to simulate so I can check how it helps in current state (and only try to simulate more or less how it will help with other improvements). I will take another look at it to see what is the real improvement.
I was also thinking about how such approach (comparing start\end or if previous text is a substring of the new one) could help here and if it can help solve most of the issue (same as complex diff would). |
I did some testing with collaborative editing to check how this fix on its own may improve composition handling. Tested scenarios:
Tested on Chrome, FF and Safari with macOS accent panel, Spanish accent and Japanese Hiragana input:
The important thing to keep in mind is that it works (or rather doesn't work) the same way before and after applying the fix with smart text node rendering. The reason for this is mentioned in one of the comments above (https://github.com/ckeditor/ckeditor5-engine/issues/403#issuecomment-374646680):
So for all tested scenario simply Then I changed the code by removing
As for FF (haven't observed in other browsers) it seems that there is more general issue. When text before selection is manipulated between So there is visible improvement. Not for all cases, but this fix may definitely helps in some of them. The other observation I had is that before this change (the temporary code change mentioned on the beginning of this section) whole text nodes were replaced by |
We have decided to try approach with the simpler diff:
As mentioned in the above comment, similar technique is already used when handling text mutations. The interesting thing is that also Mutations are only fired for typing so there are two basic cases:
and those are not the cases in which |
The diffing mechanism mentioned above will be introduced in https://github.com/ckeditor/ckeditor5-utils/issues/235. |
I switched to |
Results are the same when using
This means
|
Other: Renderer now uses partial text replacing when updating text nodes instead of replacing entire nodes. Closes #403.
We could consider using
TextNode.replaceData
andTextNode.appendData
instead of overwritingdata
property. We should check if it improves anything. It may help browsers to properly introduce changes, not to move selection if it is in the node we change and helps avoiding breaking composition.The text was updated successfully, but these errors were encountered: