Schema#addChildCheck
leads to performance problems
#15834
Labels
domain:performance
This issue reports a problem or potential improvement regarding editor performance.
package:engine
support:2
An issue reported by a commercially licensed client.
type:improvement
This issue reports a possible enhancement of an existing feature.
Milestone
📝 Provide a description of the improvement
Currently, we can use
Schema#addChildCheck()
to add custom callback that can affect whether some node is allowed at given place in model structure. The callbacks were meant to be flexible, you can check anything and as you wish in it. Same forSchema#addAttributeCheck()
.Unfortunately, this can lead to performance problems if you start using many of them. Why?
Schema is checked very frequently by multiple features. Most commands check either whether it can insert a child at given place or whether it is possible to apply attribute for given selection. This is refreshed after every selection change and model change. With a rich set of plugins, you may have as many as 10-15 checks every keystroke. When multiple callbacks like this are added, this can become 50-100 callbacks each keystroke, and you may start to see downgrade in the editor responsiveness, especially on slower machines.
This is of course not necessary. There's no need for features A,B,C,D... to check whether feature X complies with schema. But since these are very simple callbacks, they are fired each time the schema checked by each feature.
However, we use declarative schema so much, how come it does not affect performance?
Well, declarative schema is checked only for a specified element/attribute.
Schema#checkChild
andSchema#checkAttribute
gets a definition for specified element/attribute and only checks it. As a result feature X checks only feature X rules.We should try to limit how many custom callbacks are called after each model update.
First, we should add additional parameter to
addChildCheck()
andaddAttributeCheck()
that will specify for which element/attribute this callback is declared. We can have this optional to still allow for very general checks but we would assume that these are used very rarely, for complex custom plugins, and maybe there's one or two such callbacks in the editor at most.We should try to keep
checkChild
andcheckAttribute
events for backward compatibility but it might be that the arguments for these events will change, which will affect alladdChildCheck()
uses. But... as I look at it know, it shouldn't change, as we normalize the arguments in the highest priority listener:So, after adding the extra parameter, we have two ways of solving the performance issue.
First -- instead of simply adding the callback as an event listener, we would save it in an internal map in
Schema
. Then, whencheckChild()
is called, before doing default declarative check, we would go through all the registered callbacks for given definition.Second -- we could use namespaced events. So, if I check schema for
paragraph
, thencheckChild:paragraph
is called. In this solution, we don't need to change much howaddChildCheck()
works. We will simply add callbacks to the namespaced events. However,checkChild()
cannot be a decorated method any longer. Instead, it would have to be like this:I am fine with both solutions. One thing that I don't like about the second solution a bit is that we have a method (
childCheck()
) which behaves much like a decorated method but isn't really, which may be confusing? But this is a tiny nitpick.The text was updated successfully, but these errors were encountered: